blob: 2a906d81b40b53c2ddcc0e743087d4ea3d35c28f [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
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070054/**=========================================================================
Jeff Johnson295189b2012-06-20 16:38:30 -070055
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070056 EDIT HISTORY FOR FILE
Jeff Johnson295189b2012-06-20 16:38:30 -070057
58
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070059 This section contains comments describing changes made to the module.
60 Notice that changes are listed in reverse chronological order.
Jeff Johnson295189b2012-06-20 16:38:30 -070061
62
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070063 $Header:$ $DateTime: $ $Author: $
Jeff Johnson295189b2012-06-20 16:38:30 -070064
65
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070066 when who what, where, why
Jeff Johnson295189b2012-06-20 16:38:30 -070067 -------- --- --------------------------------------------------------
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070068 21/12/09 Ashwani Created module.
Jeff Johnson295189b2012-06-20 16:38:30 -070069
70 07/06/10 Kumar Deepak Implemented cfg80211 callbacks for ANDROID
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070071 Ganesh K
Jeff Johnson295189b2012-06-20 16:38:30 -070072 ==========================================================================*/
73
Jeff Johnson295189b2012-06-20 16:38:30 -070074
75#include <linux/version.h>
76#include <linux/module.h>
77#include <linux/kernel.h>
78#include <linux/init.h>
79#include <linux/wireless.h>
80#include <wlan_hdd_includes.h>
81#include <net/arp.h>
82#include <net/cfg80211.h>
83#include <linux/wireless.h>
84#include <wlan_hdd_wowl.h>
85#include <aniGlobal.h>
86#include "ccmApi.h"
87#include "sirParams.h"
88#include "dot11f.h"
89#include "wlan_hdd_assoc.h"
90#include "wlan_hdd_wext.h"
91#include "sme_Api.h"
92#include "wlan_hdd_p2p.h"
93#include "wlan_hdd_cfg80211.h"
94#include "wlan_hdd_hostapd.h"
95#include "sapInternal.h"
96#include "wlan_hdd_softap_tx_rx.h"
97#include "wlan_hdd_main.h"
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +053098#include "wlan_hdd_assoc.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070099#ifdef WLAN_BTAMP_FEATURE
100#include "bap_hdd_misc.h"
101#endif
102#include <qc_sap_ioctl.h>
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800103#ifdef FEATURE_WLAN_TDLS
104#include "wlan_hdd_tdls.h"
105#endif
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +0530106#include "wlan_nv.h"
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
Gopichand Nakkala356fb102013-03-06 12:34:04 +0530147#ifdef WLAN_FEATURE_VOWIFI_11R
148#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
149#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
150#endif
151
Jeff Johnson295189b2012-06-20 16:38:30 -0700152static const u32 hdd_cipher_suites[] =
153{
154 WLAN_CIPHER_SUITE_WEP40,
155 WLAN_CIPHER_SUITE_WEP104,
156 WLAN_CIPHER_SUITE_TKIP,
157#ifdef FEATURE_WLAN_CCX
158#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
159 WLAN_CIPHER_SUITE_KRK,
160 WLAN_CIPHER_SUITE_CCMP,
161#else
162 WLAN_CIPHER_SUITE_CCMP,
163#endif
164#ifdef FEATURE_WLAN_WAPI
165 WLAN_CIPHER_SUITE_SMS4,
166#endif
Chet Lanctot186b5732013-03-18 10:26:30 -0700167#ifdef WLAN_FEATURE_11W
168 WLAN_CIPHER_SUITE_AES_CMAC,
169#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700170};
171
172static inline int is_broadcast_ether_addr(const u8 *addr)
173{
174 return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&
175 (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
176}
177
178static struct ieee80211_channel hdd_channels_2_4_GHZ[] =
179{
180 HDD2GHZCHAN(2412, 1, 0) ,
181 HDD2GHZCHAN(2417, 2, 0) ,
182 HDD2GHZCHAN(2422, 3, 0) ,
183 HDD2GHZCHAN(2427, 4, 0) ,
184 HDD2GHZCHAN(2432, 5, 0) ,
185 HDD2GHZCHAN(2437, 6, 0) ,
186 HDD2GHZCHAN(2442, 7, 0) ,
187 HDD2GHZCHAN(2447, 8, 0) ,
188 HDD2GHZCHAN(2452, 9, 0) ,
189 HDD2GHZCHAN(2457, 10, 0) ,
190 HDD2GHZCHAN(2462, 11, 0) ,
191 HDD2GHZCHAN(2467, 12, 0) ,
192 HDD2GHZCHAN(2472, 13, 0) ,
193 HDD2GHZCHAN(2484, 14, 0) ,
194};
195
Jeff Johnson295189b2012-06-20 16:38:30 -0700196static struct ieee80211_channel hdd_social_channels_2_4_GHZ[] =
197{
198 HDD2GHZCHAN(2412, 1, 0) ,
199 HDD2GHZCHAN(2437, 6, 0) ,
200 HDD2GHZCHAN(2462, 11, 0) ,
201};
Jeff Johnson295189b2012-06-20 16:38:30 -0700202
203static struct ieee80211_channel hdd_channels_5_GHZ[] =
204{
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700205 HDD5GHZCHAN(4920, 240, 0) ,
206 HDD5GHZCHAN(4940, 244, 0) ,
207 HDD5GHZCHAN(4960, 248, 0) ,
208 HDD5GHZCHAN(4980, 252, 0) ,
209 HDD5GHZCHAN(5040, 208, 0) ,
210 HDD5GHZCHAN(5060, 212, 0) ,
211 HDD5GHZCHAN(5080, 216, 0) ,
Jeff Johnson295189b2012-06-20 16:38:30 -0700212 HDD5GHZCHAN(5180, 36, 0) ,
213 HDD5GHZCHAN(5200, 40, 0) ,
214 HDD5GHZCHAN(5220, 44, 0) ,
215 HDD5GHZCHAN(5240, 48, 0) ,
216 HDD5GHZCHAN(5260, 52, 0) ,
217 HDD5GHZCHAN(5280, 56, 0) ,
218 HDD5GHZCHAN(5300, 60, 0) ,
219 HDD5GHZCHAN(5320, 64, 0) ,
220 HDD5GHZCHAN(5500,100, 0) ,
221 HDD5GHZCHAN(5520,104, 0) ,
222 HDD5GHZCHAN(5540,108, 0) ,
223 HDD5GHZCHAN(5560,112, 0) ,
224 HDD5GHZCHAN(5580,116, 0) ,
225 HDD5GHZCHAN(5600,120, 0) ,
226 HDD5GHZCHAN(5620,124, 0) ,
227 HDD5GHZCHAN(5640,128, 0) ,
228 HDD5GHZCHAN(5660,132, 0) ,
229 HDD5GHZCHAN(5680,136, 0) ,
230 HDD5GHZCHAN(5700,140, 0) ,
231 HDD5GHZCHAN(5745,149, 0) ,
232 HDD5GHZCHAN(5765,153, 0) ,
233 HDD5GHZCHAN(5785,157, 0) ,
234 HDD5GHZCHAN(5805,161, 0) ,
235 HDD5GHZCHAN(5825,165, 0) ,
236};
237
238static struct ieee80211_rate g_mode_rates[] =
239{
240 HDD_G_MODE_RATETAB(10, 0x1, 0),
241 HDD_G_MODE_RATETAB(20, 0x2, 0),
242 HDD_G_MODE_RATETAB(55, 0x4, 0),
243 HDD_G_MODE_RATETAB(110, 0x8, 0),
244 HDD_G_MODE_RATETAB(60, 0x10, 0),
245 HDD_G_MODE_RATETAB(90, 0x20, 0),
246 HDD_G_MODE_RATETAB(120, 0x40, 0),
247 HDD_G_MODE_RATETAB(180, 0x80, 0),
248 HDD_G_MODE_RATETAB(240, 0x100, 0),
249 HDD_G_MODE_RATETAB(360, 0x200, 0),
250 HDD_G_MODE_RATETAB(480, 0x400, 0),
251 HDD_G_MODE_RATETAB(540, 0x800, 0),
252};
253
254static struct ieee80211_rate a_mode_rates[] =
255{
256 HDD_G_MODE_RATETAB(60, 0x10, 0),
257 HDD_G_MODE_RATETAB(90, 0x20, 0),
258 HDD_G_MODE_RATETAB(120, 0x40, 0),
259 HDD_G_MODE_RATETAB(180, 0x80, 0),
260 HDD_G_MODE_RATETAB(240, 0x100, 0),
261 HDD_G_MODE_RATETAB(360, 0x200, 0),
262 HDD_G_MODE_RATETAB(480, 0x400, 0),
263 HDD_G_MODE_RATETAB(540, 0x800, 0),
264};
265
266static struct ieee80211_supported_band wlan_hdd_band_2_4_GHZ =
267{
268 .channels = hdd_channels_2_4_GHZ,
269 .n_channels = ARRAY_SIZE(hdd_channels_2_4_GHZ),
270 .band = IEEE80211_BAND_2GHZ,
271 .bitrates = g_mode_rates,
272 .n_bitrates = g_mode_rates_size,
273 .ht_cap.ht_supported = 1,
274 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
275 | IEEE80211_HT_CAP_GRN_FLD
276 | IEEE80211_HT_CAP_DSSSCCK40
277 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
278 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
279 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
280 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
281 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
282 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
283};
284
Jeff Johnson295189b2012-06-20 16:38:30 -0700285static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_GHZ =
286{
287 .channels = hdd_social_channels_2_4_GHZ,
288 .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_GHZ),
289 .band = IEEE80211_BAND_2GHZ,
290 .bitrates = g_mode_rates,
291 .n_bitrates = g_mode_rates_size,
292 .ht_cap.ht_supported = 1,
293 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
294 | IEEE80211_HT_CAP_GRN_FLD
295 | IEEE80211_HT_CAP_DSSSCCK40
296 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
297 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
298 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
299 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
300 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
301 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
302};
Jeff Johnson295189b2012-06-20 16:38:30 -0700303
304static struct ieee80211_supported_band wlan_hdd_band_5_GHZ =
305{
306 .channels = hdd_channels_5_GHZ,
307 .n_channels = ARRAY_SIZE(hdd_channels_5_GHZ),
308 .band = IEEE80211_BAND_5GHZ,
309 .bitrates = a_mode_rates,
310 .n_bitrates = a_mode_rates_size,
311 .ht_cap.ht_supported = 1,
312 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
313 | IEEE80211_HT_CAP_GRN_FLD
314 | IEEE80211_HT_CAP_DSSSCCK40
315 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
316 | IEEE80211_HT_CAP_SGI_40
317 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
318 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
319 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
320 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
321 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
322 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
323};
324
325/* This structure contain information what kind of frame are expected in
326 TX/RX direction for each kind of interface */
327static const struct ieee80211_txrx_stypes
328wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
329 [NL80211_IFTYPE_STATION] = {
330 .tx = 0xffff,
331 .rx = BIT(SIR_MAC_MGMT_ACTION) |
332 BIT(SIR_MAC_MGMT_PROBE_REQ),
333 },
334 [NL80211_IFTYPE_AP] = {
335 .tx = 0xffff,
336 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
337 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
338 BIT(SIR_MAC_MGMT_PROBE_REQ) |
339 BIT(SIR_MAC_MGMT_DISASSOC) |
340 BIT(SIR_MAC_MGMT_AUTH) |
341 BIT(SIR_MAC_MGMT_DEAUTH) |
342 BIT(SIR_MAC_MGMT_ACTION),
343 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700344 [NL80211_IFTYPE_P2P_CLIENT] = {
345 .tx = 0xffff,
346 .rx = BIT(SIR_MAC_MGMT_ACTION) |
347 BIT(SIR_MAC_MGMT_PROBE_REQ),
348 },
349 [NL80211_IFTYPE_P2P_GO] = {
350 /* This is also same as for SoftAP */
351 .tx = 0xffff,
352 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
353 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
354 BIT(SIR_MAC_MGMT_PROBE_REQ) |
355 BIT(SIR_MAC_MGMT_DISASSOC) |
356 BIT(SIR_MAC_MGMT_AUTH) |
357 BIT(SIR_MAC_MGMT_DEAUTH) |
358 BIT(SIR_MAC_MGMT_ACTION),
359 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700360};
361
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800362#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800363static const struct ieee80211_iface_limit
364wlan_hdd_iface_limit[] = {
365 {
Sunil Ravia72c3992013-01-31 06:12:22 -0800366 /* max = 3 ; Our driver create two interfaces during driver init
367 * wlan0 and p2p0 interfaces. p2p0 is considered as station
368 * interface until a group is formed. In JB architecture, once the
369 * group is formed, interface type of p2p0 is changed to P2P GO or
370 * Client.
371 * When supplicant remove the group, it first issue a set interface
372 * cmd to change the mode back to Station. In JB this works fine as
373 * we advertize two station type interface during driver init.
374 * Some vendors create separate interface for P2P GO/Client,
375 * after group formation(Third one). But while group remove
376 * supplicant first tries to change the mode(3rd interface) to STATION
377 * But as we advertized only two sta type interfaces nl80211 was
378 * returning error for the third one which was leading to failure in
379 * delete interface. Ideally while removing the group, supplicant
380 * should not try to change the 3rd interface mode to Station type.
381 * Till we get a fix in wpa_supplicant, we advertize max STA
382 * interface type to 3
383 */
384 .max = 3,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800385 .types = BIT(NL80211_IFTYPE_STATION),
386 },
387 {
388 .max = 1,
389 .types = BIT(NL80211_IFTYPE_AP),
390 },
391 {
392 .max = 1,
393 .types = BIT(NL80211_IFTYPE_P2P_GO) |
394 BIT(NL80211_IFTYPE_P2P_CLIENT),
395 },
396};
397
398/* By default, only single channel concurrency is allowed */
399static struct ieee80211_iface_combination
400wlan_hdd_iface_combination = {
401 .limits = wlan_hdd_iface_limit,
402 .num_different_channels = 1,
Sunil Ravia72c3992013-01-31 06:12:22 -0800403 /*
404 * max = WLAN_MAX_INTERFACES ; JellyBean architecture creates wlan0
405 * and p2p0 interfaces during driver init
406 * Some vendors create separate interface for P2P operations.
407 * wlan0: STA interface
408 * p2p0: P2P Device interface, action frames goes
409 * through this interface.
410 * p2p-xx: P2P interface, After GO negotiation this interface is
411 * created for p2p operations(GO/CLIENT interface).
412 */
413 .max_interfaces = WLAN_MAX_INTERFACES,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800414 .n_limits = ARRAY_SIZE(wlan_hdd_iface_limit),
415 .beacon_int_infra_match = false,
416};
417#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800418
Jeff Johnson295189b2012-06-20 16:38:30 -0700419static struct cfg80211_ops wlan_hdd_cfg80211_ops;
420
421/* Data rate 100KBPS based on IE Index */
422struct index_data_rate_type
423{
424 v_U8_t beacon_rate_index;
425 v_U16_t supported_rate[4];
426};
427
428/* 11B, 11G Rate table include Basic rate and Extended rate
429 The IDX field is the rate index
430 The HI field is the rate when RSSI is strong or being ignored
431 (in this case we report actual rate)
432 The MID field is the rate when RSSI is moderate
433 (in this case we cap 11b rates at 5.5 and 11g rates at 24)
434 The LO field is the rate when RSSI is low
435 (in this case we don't report rates, actual current rate used)
436 */
437static const struct
438{
439 v_U8_t beacon_rate_index;
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700440 v_U16_t supported_rate[4];
Jeff Johnson295189b2012-06-20 16:38:30 -0700441} supported_data_rate[] =
442{
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700443/* IDX HI HM LM LO (RSSI-based index */
444 {2, { 10, 10, 10, 0}},
445 {4, { 20, 20, 10, 0}},
446 {11, { 55, 20, 10, 0}},
447 {12, { 60, 55, 20, 0}},
448 {18, { 90, 55, 20, 0}},
449 {22, {110, 55, 20, 0}},
450 {24, {120, 90, 60, 0}},
451 {36, {180, 120, 60, 0}},
452 {44, {220, 180, 60, 0}},
453 {48, {240, 180, 90, 0}},
454 {66, {330, 180, 90, 0}},
455 {72, {360, 240, 90, 0}},
456 {96, {480, 240, 120, 0}},
457 {108, {540, 240, 120, 0}}
Jeff Johnson295189b2012-06-20 16:38:30 -0700458};
459
460/* MCS Based rate table */
461static struct index_data_rate_type supported_mcs_rate[] =
462{
463/* MCS L20 L40 S20 S40 */
464 {0, {65, 135, 72, 150}},
465 {1, {130, 270, 144, 300}},
466 {2, {195, 405, 217, 450}},
467 {3, {260, 540, 289, 600}},
468 {4, {390, 810, 433, 900}},
469 {5, {520, 1080, 578, 1200}},
470 {6, {585, 1215, 650, 1350}},
471 {7, {650, 1350, 722, 1500}}
472};
473
Leo Chang6f8870f2013-03-26 18:11:36 -0700474#ifdef WLAN_FEATURE_11AC
475
476#define DATA_RATE_11AC_MCS_MASK 0x0F
477
478struct index_vht_data_rate_type
479{
480 v_U8_t beacon_rate_index;
481 v_U16_t supported_rate[2];
482};
483
484typedef enum
485{
486 DATA_RATE_11AC_MAX_MCS_7,
487 DATA_RATE_11AC_MAX_MCS_8,
488 DATA_RATE_11AC_MAX_MCS_9,
489 DATA_RATE_11AC_MAX_MCS_NA
490} eDataRate11ACMaxMcs;
491
492/* MCS Based VHT rate table */
493static struct index_vht_data_rate_type supported_vht_mcs_rate[] =
494{
495/* MCS L80 S80 */
496 {0, {293, 325}},
497 {1, {585, 650}},
498 {2, {878, 975}},
499 {3, {1170, 1300}},
500 {4, {1755, 1950}},
501 {5, {2340, 2600}},
502 {6, {2633, 2925}},
503 {7, {2925, 3250}},
504 {8, {3510, 3900}},
505 {9, {3900, 4333}}
506};
507#endif /* WLAN_FEATURE_11AC */
508
Jeff Johnson295189b2012-06-20 16:38:30 -0700509extern struct net_device_ops net_ops_struct;
510
511/*
512 * FUNCTION: wlan_hdd_cfg80211_init
513 * This function is called by hdd_wlan_startup()
514 * during initialization.
515 * This function is used to initialize and register wiphy structure.
516 */
517struct wiphy *wlan_hdd_cfg80211_init(int priv_size)
518{
519 struct wiphy *wiphy;
520 ENTER();
521
522 /*
523 * Create wiphy device
524 */
525 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
526
527 if (!wiphy)
528 {
529 /* Print error and jump into err label and free the memory */
530 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__);
531 return NULL;
532 }
533
534 return wiphy;
535}
536
537/*
538 * FUNCTION: wlan_hdd_cfg80211_update_band
539 * This function is called from the supplicant through a
540 * private ioctl to change the band value
541 */
542int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
543{
Jeff Johnsone7245742012-09-05 17:12:55 -0700544 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700545 switch(eBand)
546 {
547 case eCSR_BAND_24:
548 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
549 wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
550 break;
551 case eCSR_BAND_5G:
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700552 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700553 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
554 break;
555 case eCSR_BAND_ALL:
556 default:
557 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
558 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
559 }
560 return 0;
561}
562/*
563 * FUNCTION: wlan_hdd_cfg80211_init
564 * This function is called by hdd_wlan_startup()
565 * during initialization.
566 * This function is used to initialize and register wiphy structure.
567 */
568int wlan_hdd_cfg80211_register(struct device *dev,
569 struct wiphy *wiphy,
570 hdd_config_t *pCfg
571 )
572{
Jeff Johnsone7245742012-09-05 17:12:55 -0700573 ENTER();
574
Jeff Johnson295189b2012-06-20 16:38:30 -0700575 /* Now bind the underlying wlan device with wiphy */
576 set_wiphy_dev(wiphy, dev);
577
578 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
579
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700580 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700581
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700582#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700583 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
584 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
585 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
Jeff Johnsone7245742012-09-05 17:12:55 -0700586 | WIPHY_FLAG_OFFCHAN_TX;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700587#endif
Srinivas Girigowda640728a2013-03-28 12:21:54 -0700588#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
589 if (pCfg->isFastTransitionEnabled
James Zmuda77fb5ae2013-01-29 08:00:17 -0800590#ifdef FEATURE_WLAN_LFR
Srinivas Girigowda640728a2013-03-28 12:21:54 -0700591 || pCfg->isFastRoamIniFeatureEnabled
592#endif
593#ifdef FEATURE_WLAN_CCX
594 || pCfg->isCcxIniFeatureEnabled
595#endif
596 )
597 {
598 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
599 }
James Zmuda77fb5ae2013-01-29 08:00:17 -0800600#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800601#ifdef FEATURE_WLAN_TDLS
602 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
603 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
604#endif
605
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700606 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
607 driver can still register regulatory callback and
608 it will get CRDA setting in wiphy->band[], but
609 driver need to determine what to do with both
610 regulatory settings */
611 wiphy->reg_notifier = wlan_hdd_crda_reg_notifier;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700612
Jeff Johnson295189b2012-06-20 16:38:30 -0700613 wiphy->max_scan_ssids = MAX_SCAN_SSID;
614
615 wiphy->max_scan_ie_len = 200 ; //TODO: define a macro
616
617 /* Supports STATION & AD-HOC modes right now */
618 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
619 | BIT(NL80211_IFTYPE_ADHOC)
Jeff Johnson295189b2012-06-20 16:38:30 -0700620 | BIT(NL80211_IFTYPE_P2P_CLIENT)
621 | BIT(NL80211_IFTYPE_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -0700622 | BIT(NL80211_IFTYPE_AP);
623
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800624#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800625 if( pCfg->enableMCC )
626 {
627 /* Currently, supports up to two channels */
628 wlan_hdd_iface_combination.num_different_channels = 2;
629
630 if( !pCfg->allowMCCGODiffBI )
631 wlan_hdd_iface_combination.beacon_int_infra_match = true;
632
633 }
634 wiphy->iface_combinations = &wlan_hdd_iface_combination;
635 wiphy->n_iface_combinations = 1;
636#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800637
Jeff Johnson295189b2012-06-20 16:38:30 -0700638 /* Before registering we need to update the ht capabilitied based
639 * on ini values*/
640 if( !pCfg->ShortGI20MhzEnable )
641 {
642 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
643 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
644 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
645 }
646
647 if( !pCfg->ShortGI40MhzEnable )
648 {
649 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
650 }
651
652 if( !pCfg->nChannelBondingMode5GHz )
653 {
654 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
655 }
656
657 /*Initialize band capability*/
658 switch(pCfg->nBandCapability)
659 {
660 case eCSR_BAND_24:
661 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
662 break;
663 case eCSR_BAND_5G:
Jeff Johnson295189b2012-06-20 16:38:30 -0700664 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700665 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
666 break;
667 case eCSR_BAND_ALL:
668 default:
669 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
670 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
671 }
672 /*Initialise the supported cipher suite details*/
673 wiphy->cipher_suites = hdd_cipher_suites;
674 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
675
676 /*signal strength in mBm (100*dBm) */
677 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
678
679#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -0700680 wiphy->max_remain_on_channel_duration = 1000;
681#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700682
683 /* Register our wiphy dev with cfg80211 */
684 if (0 > wiphy_register(wiphy))
685 {
686 /* print eror */
687 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
688 return -EIO;
689 }
690
691 EXIT();
692 return 0;
693}
694
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700695/* In this function we will try to get default country code from crda.
696 If the gCrdaDefaultCountryCode is configured in ini file,
697 we will try to call user space crda to get the regulatory settings for
698 that country. We will timeout if we can't get it from crda.
699 It's called by hdd_wlan_startup() after wlan_hdd_cfg80211_register.
700*/
701int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg)
702{
703 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
704 if (memcmp(pCfg->crdaDefaultCountryCode,
705 CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) != 0)
706 {
707 init_completion(&pHddCtx->driver_crda_req);
708 regulatory_hint(wiphy, pCfg->crdaDefaultCountryCode);
709 wait_for_completion_interruptible_timeout(&pHddCtx->driver_crda_req,
710 CRDA_WAIT_TIME);
Yunsen Wange3ba1fb2013-04-05 15:04:43 -0700711 /* if the country is not found from current regulatory.bin,
712 fall back to world domain */
713 if (is_crda_regulatory_entry_valid() == VOS_FALSE)
714 crda_regulatory_entry_default(pCfg->crdaDefaultCountryCode, NUM_REG_DOMAINS-1);
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700715 }
716 return 0;
717}
718
Jeff Johnson295189b2012-06-20 16:38:30 -0700719/* In this function we will do all post VOS start initialization.
720 In this function we will register for all frame in which supplicant
721 is interested.
722*/
723void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
724{
Jeff Johnson295189b2012-06-20 16:38:30 -0700725 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
726 /* Register for all P2P action, public action etc frames */
727 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
728
Jeff Johnsone7245742012-09-05 17:12:55 -0700729 ENTER();
730
Jeff Johnson295189b2012-06-20 16:38:30 -0700731 /* Right now we are registering these frame when driver is getting
732 initialized. Once we will move to 2.6.37 kernel, in which we have
733 frame register ops, we will move this code as a part of that */
734 /* GAS Initial Request */
735 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
736 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
737
738 /* GAS Initial Response */
739 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
740 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
741
742 /* GAS Comeback Request */
743 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
744 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
745
746 /* GAS Comeback Response */
747 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
748 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
749
750 /* P2P Public Action */
751 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
752 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
753 P2P_PUBLIC_ACTION_FRAME_SIZE );
754
755 /* P2P Action */
756 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
757 (v_U8_t*)P2P_ACTION_FRAME,
758 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -0700759
760#ifdef WLAN_FEATURE_11W
761 /* SA Query Response Action Frame */
762 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
763 (v_U8_t*)SA_QUERY_FRAME_RSP,
764 SA_QUERY_FRAME_RSP_SIZE );
765#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -0700766}
767
768void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
769{
Jeff Johnson295189b2012-06-20 16:38:30 -0700770 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
771 /* Register for all P2P action, public action etc frames */
772 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
773
Jeff Johnsone7245742012-09-05 17:12:55 -0700774 ENTER();
775
Jeff Johnson295189b2012-06-20 16:38:30 -0700776 /* Right now we are registering these frame when driver is getting
777 initialized. Once we will move to 2.6.37 kernel, in which we have
778 frame register ops, we will move this code as a part of that */
779 /* GAS Initial Request */
780
781 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
782 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
783
784 /* GAS Initial Response */
785 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
786 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
787
788 /* GAS Comeback Request */
789 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
790 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
791
792 /* GAS Comeback Response */
793 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
794 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
795
796 /* P2P Public Action */
797 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
798 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
799 P2P_PUBLIC_ACTION_FRAME_SIZE );
800
801 /* P2P Action */
802 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
803 (v_U8_t*)P2P_ACTION_FRAME,
804 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -0700805
806#ifdef WLAN_FEATURE_11W
807 /* SA Query Response Action Frame */
808 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
809 (v_U8_t*)SA_QUERY_FRAME_RSP,
810 SA_QUERY_FRAME_RSP_SIZE );
811#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -0700812}
813
814#ifdef FEATURE_WLAN_WAPI
815void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
816 const u8 *mac_addr, u8 *key , int key_Len)
817{
818 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
819 tCsrRoamSetKey setKey;
820 v_BOOL_t isConnected = TRUE;
821 int status = 0;
822 v_U32_t roamId= 0xFF;
823 tANI_U8 *pKeyPtr = NULL;
824 int n = 0;
825
826 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
827 __func__,pAdapter->device_mode);
828
Gopichand Nakkalae7480202013-02-11 15:24:22 +0530829 vos_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Jeff Johnson295189b2012-06-20 16:38:30 -0700830 setKey.keyId = key_index; // Store Key ID
831 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
832 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
833 setKey.paeRole = 0 ; // the PAE role
834 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
835 {
836 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
837 }
838 else
839 {
840 isConnected = hdd_connIsConnected(pHddStaCtx);
841 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
842 }
843 setKey.keyLength = key_Len;
844 pKeyPtr = setKey.Key;
845 memcpy( pKeyPtr, key, key_Len);
846
847 hddLog(VOS_TRACE_LEVEL_INFO,"\n%s: WAPI KEY LENGTH:0x%04x",
848 __func__, key_Len);
849 for (n = 0 ; n < key_Len; n++)
850 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
851 __func__,n,setKey.Key[n]);
852
853 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
854 if ( isConnected )
855 {
856 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
857 pAdapter->sessionId, &setKey, &roamId );
858 }
859 if ( status != 0 )
860 {
861 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
862 "[%4d] sme_RoamSetKey returned ERROR status= %d",
863 __LINE__, status );
864 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
865 }
866}
867#endif /* FEATURE_WLAN_WAPI*/
868
869#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
870int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
871 beacon_data_t **ppBeacon,
872 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700873#else
874int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
875 beacon_data_t **ppBeacon,
876 struct cfg80211_beacon_data *params,
877 int dtim_period)
878#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700879{
880 int size;
881 beacon_data_t *beacon = NULL;
882 beacon_data_t *old = NULL;
883 int head_len,tail_len;
884
Jeff Johnsone7245742012-09-05 17:12:55 -0700885 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700886 if (params->head && !params->head_len)
887 return -EINVAL;
888
889 old = pAdapter->sessionCtx.ap.beacon;
890
891 if (!params->head && !old)
892 return -EINVAL;
893
894 if (params->tail && !params->tail_len)
895 return -EINVAL;
896
897#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
898 /* Kernel 3.0 is not updating dtim_period for set beacon */
899 if (!params->dtim_period)
900 return -EINVAL;
901#endif
902
903 if(params->head)
904 head_len = params->head_len;
905 else
906 head_len = old->head_len;
907
908 if(params->tail || !old)
909 tail_len = params->tail_len;
910 else
911 tail_len = old->tail_len;
912
913 size = sizeof(beacon_data_t) + head_len + tail_len;
914
915 beacon = kzalloc(size, GFP_KERNEL);
916
917 if( beacon == NULL )
918 return -ENOMEM;
919
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700920#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700921 if(params->dtim_period || !old )
922 beacon->dtim_period = params->dtim_period;
923 else
924 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700925#else
926 if(dtim_period || !old )
927 beacon->dtim_period = dtim_period;
928 else
929 beacon->dtim_period = old->dtim_period;
930#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700931
932 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
933 beacon->tail = beacon->head + head_len;
934 beacon->head_len = head_len;
935 beacon->tail_len = tail_len;
936
937 if(params->head) {
938 memcpy (beacon->head,params->head,beacon->head_len);
939 }
940 else {
941 if(old)
942 memcpy (beacon->head,old->head,beacon->head_len);
943 }
944
945 if(params->tail) {
946 memcpy (beacon->tail,params->tail,beacon->tail_len);
947 }
948 else {
949 if(old)
950 memcpy (beacon->tail,old->tail,beacon->tail_len);
951 }
952
953 *ppBeacon = beacon;
954
955 kfree(old);
956
957 return 0;
958
959}
Jeff Johnson295189b2012-06-20 16:38:30 -0700960
961v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
962{
963 int left = length;
964 v_U8_t *ptr = pIes;
965 v_U8_t elem_id,elem_len;
966
967 while(left >= 2)
968 {
969 elem_id = ptr[0];
970 elem_len = ptr[1];
971 left -= 2;
972 if(elem_len > left)
973 {
974 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700975 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -0700976 eid,elem_len,left);
977 return NULL;
978 }
979 if (elem_id == eid)
980 {
981 return ptr;
982 }
983
984 left -= elem_len;
985 ptr += (elem_len + 2);
986 }
987 return NULL;
988}
989
Jeff Johnson295189b2012-06-20 16:38:30 -0700990/* Check if rate is 11g rate or not */
991static int wlan_hdd_rate_is_11g(u8 rate)
992{
993 u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 104}; /* actual rate * 2 */
994 u8 i;
995 for (i = 0; i < 8; i++)
996 {
997 if(rate == gRateArray[i])
998 return TRUE;
999 }
1000 return FALSE;
1001}
1002
1003/* Check for 11g rate and set proper 11g only mode */
1004static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
1005 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
1006{
1007 u8 i, num_rates = pIe[0];
1008
1009 pIe += 1;
1010 for ( i = 0; i < num_rates; i++)
1011 {
1012 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
1013 {
1014 /* If rate set have 11g rate than change the mode to 11G */
1015 *pSapHw_mode = eSAP_DOT11_MODE_11g;
1016 if (pIe[i] & BASIC_RATE_MASK)
1017 {
1018 /* If we have 11g rate as basic rate, it means mode
1019 is 11g only mode.
1020 */
1021 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
1022 *pCheckRatesfor11g = FALSE;
1023 }
1024 }
1025 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
1026 {
1027 *require_ht = TRUE;
1028 }
1029 }
1030 return;
1031}
1032
1033static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
1034{
1035 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1036 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1037 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1038 u8 checkRatesfor11g = TRUE;
1039 u8 require_ht = FALSE;
1040 u8 *pIe=NULL;
1041
1042 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
1043
1044 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
1045 pBeacon->head_len, WLAN_EID_SUPP_RATES);
1046 if (pIe != NULL)
1047 {
1048 pIe += 1;
1049 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1050 &pConfig->SapHw_mode);
1051 }
1052
1053 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1054 WLAN_EID_EXT_SUPP_RATES);
1055 if (pIe != NULL)
1056 {
1057
1058 pIe += 1;
1059 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1060 &pConfig->SapHw_mode);
1061 }
1062
1063 if( pConfig->channel > 14 )
1064 {
1065 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
1066 }
1067
1068 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1069 WLAN_EID_HT_CAPABILITY);
1070
1071 if(pIe)
1072 {
1073 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
1074 if(require_ht)
1075 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
1076 }
1077}
1078
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301079static int wlan_hdd_add_ie(hdd_adapter_t* pHostapdAdapter, v_U8_t *genie,
1080 v_U8_t *total_ielen, v_U8_t *oui, v_U8_t oui_size)
1081{
1082 v_U8_t ielen = 0;
1083 v_U8_t *pIe = NULL;
1084 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1085
1086 pIe = wlan_hdd_get_vendor_oui_ie_ptr(oui, oui_size,
1087 pBeacon->tail, pBeacon->tail_len);
1088
1089 if (pIe)
1090 {
1091 ielen = pIe[1] + 2;
1092 if ((*total_ielen + ielen) <= MAX_GENIE_LEN)
1093 {
1094 vos_mem_copy(&genie[*total_ielen], pIe, ielen);
1095 }
1096 else
1097 {
1098 hddLog( VOS_TRACE_LEVEL_ERROR, "**Ie Length is too big***");
1099 return -EINVAL;
1100 }
1101 *total_ielen += ielen;
1102 }
1103 return 0;
1104}
1105
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001106#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001107static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1108 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001109#else
1110static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1111 struct cfg80211_beacon_data *params)
1112#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001113{
1114 v_U8_t *genie;
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301115 v_U8_t total_ielen = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001116 v_U8_t addIE[1] = {0};
Jeff Johnsone7245742012-09-05 17:12:55 -07001117 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001118
1119 genie = vos_mem_malloc(MAX_GENIE_LEN);
1120
1121 if(genie == NULL) {
1122
1123 return -ENOMEM;
1124 }
1125
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301126 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1127 &total_ielen, WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001128 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301129 ret = -EINVAL;
1130 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001131 }
1132
1133#ifdef WLAN_FEATURE_WFD
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301134 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1135 &total_ielen, WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE))
1136 {
1137 ret = -EINVAL;
1138 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001139 }
1140#endif
1141
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301142 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1143 &total_ielen, P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001144 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301145 ret = -EINVAL;
1146 goto done;
1147 }
1148
1149 if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode)
1150 {
1151 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1152 &total_ielen, SS_OUI_TYPE, SS_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001153 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301154 ret = -EINVAL;
1155 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001156 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001157 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001158
1159 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1160 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1161 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1162 {
1163 hddLog(LOGE,
1164 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001165 ret = -EINVAL;
1166 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001167 }
1168
1169 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1170 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1171 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1172 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1173 ==eHAL_STATUS_FAILURE)
1174 {
1175 hddLog(LOGE,
1176 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001177 ret = -EINVAL;
1178 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001179 }
1180
1181 // Added for ProResp IE
1182 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1183 {
1184 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1185 u8 probe_rsp_ie_len[3] = {0};
1186 u8 counter = 0;
1187 /* Check Probe Resp Length if it is greater then 255 then Store
1188 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1189 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1190 Store More then 255 bytes into One Variable.
1191 */
1192 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1193 {
1194 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1195 {
1196 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1197 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1198 }
1199 else
1200 {
1201 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1202 rem_probe_resp_ie_len = 0;
1203 }
1204 }
1205
1206 rem_probe_resp_ie_len = 0;
1207
1208 if (probe_rsp_ie_len[0] > 0)
1209 {
1210 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1211 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1212 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1213 probe_rsp_ie_len[0], NULL,
1214 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1215 {
1216 hddLog(LOGE,
1217 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001218 ret = -EINVAL;
1219 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001220 }
1221 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1222 }
1223
1224 if (probe_rsp_ie_len[1] > 0)
1225 {
1226 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1227 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1228 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1229 probe_rsp_ie_len[1], NULL,
1230 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1231 {
1232 hddLog(LOGE,
1233 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001234 ret = -EINVAL;
1235 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001236 }
1237 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1238 }
1239
1240 if (probe_rsp_ie_len[2] > 0)
1241 {
1242 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1243 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1244 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1245 probe_rsp_ie_len[2], NULL,
1246 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1247 {
1248 hddLog(LOGE,
1249 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001250 ret = -EINVAL;
1251 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001252 }
1253 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1254 }
1255
1256 if (probe_rsp_ie_len[1] == 0 )
1257 {
1258 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1259 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1260 eANI_BOOLEAN_FALSE) )
1261 {
1262 hddLog(LOGE,
1263 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1264 }
1265 }
1266
1267 if (probe_rsp_ie_len[2] == 0 )
1268 {
1269 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1270 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1271 eANI_BOOLEAN_FALSE) )
1272 {
1273 hddLog(LOGE,
1274 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1275 }
1276 }
1277
1278 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1279 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1280 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1281 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1282 == eHAL_STATUS_FAILURE)
1283 {
1284 hddLog(LOGE,
1285 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001286 ret = -EINVAL;
1287 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001288 }
1289 }
1290 else
1291 {
1292 // Reset WNI_CFG_PROBE_RSP Flags
1293 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1294
1295 hddLog(VOS_TRACE_LEVEL_INFO,
1296 "%s: No Probe Response IE received in set beacon",
1297 __func__);
1298 }
1299
1300 // Added for AssocResp IE
1301 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1302 {
1303 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1304 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1305 params->assocresp_ies_len, NULL,
1306 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1307 {
1308 hddLog(LOGE,
1309 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001310 ret = -EINVAL;
1311 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001312 }
1313
1314 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1315 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1316 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1317 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1318 == eHAL_STATUS_FAILURE)
1319 {
1320 hddLog(LOGE,
1321 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001322 ret = -EINVAL;
1323 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001324 }
1325 }
1326 else
1327 {
1328 hddLog(VOS_TRACE_LEVEL_INFO,
1329 "%s: No Assoc Response IE received in set beacon",
1330 __func__);
1331
1332 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1333 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1334 eANI_BOOLEAN_FALSE) )
1335 {
1336 hddLog(LOGE,
1337 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1338 }
1339 }
1340
Jeff Johnsone7245742012-09-05 17:12:55 -07001341done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001342 vos_mem_free(genie);
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301343 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07001344}
Jeff Johnson295189b2012-06-20 16:38:30 -07001345
1346/*
1347 * FUNCTION: wlan_hdd_validate_operation_channel
1348 * called by wlan_hdd_cfg80211_start_bss() and
1349 * wlan_hdd_cfg80211_set_channel()
1350 * This function validates whether given channel is part of valid
1351 * channel list.
1352 */
1353static VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
1354{
1355
1356 v_U32_t num_ch = 0;
1357 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1358 u32 indx = 0;
1359 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301360 v_U8_t fValidChannel = FALSE, count = 0;
1361 hdd_config_t *hdd_pConfig_ini= (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07001362
1363 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1364
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301365 if ( hdd_pConfig_ini->sapAllowAllChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001366 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301367 /* Validate the channel */
1368 for (count = RF_CHAN_1 ; count <= RF_CHAN_165 ; count++)
Jeff Johnson295189b2012-06-20 16:38:30 -07001369 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301370 if ( channel == rfChannels[count].channelNum )
1371 {
1372 fValidChannel = TRUE;
1373 break;
1374 }
1375 }
1376 if (fValidChannel != TRUE)
1377 {
1378 hddLog(VOS_TRACE_LEVEL_ERROR,
1379 "%s: Invalid Channel [%d]", __func__, channel);
1380 return VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001381 }
1382 }
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301383 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001384 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301385 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1386 valid_ch, &num_ch))
1387 {
1388 hddLog(VOS_TRACE_LEVEL_ERROR,
1389 "%s: failed to get valid channel list", __func__);
1390 return VOS_STATUS_E_FAILURE;
1391 }
1392 for (indx = 0; indx < num_ch; indx++)
1393 {
1394 if (channel == valid_ch[indx])
1395 {
1396 break;
1397 }
1398 }
1399
1400 if (indx >= num_ch)
1401 {
1402 hddLog(VOS_TRACE_LEVEL_ERROR,
1403 "%s: Invalid Channel [%d]", __func__, channel);
1404 return VOS_STATUS_E_FAILURE;
1405 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001406 }
1407 return VOS_STATUS_SUCCESS;
1408
1409}
1410
Viral Modi3a32cc52013-02-08 11:14:52 -08001411/**
1412 * FUNCTION: wlan_hdd_cfg80211_set_channel
1413 * This function is used to set the channel number
1414 */
1415static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
1416 struct ieee80211_channel *chan,
1417 enum nl80211_channel_type channel_type
1418 )
1419{
1420 v_U32_t num_ch = 0;
Jeff Johnson4416a782013-03-25 14:17:50 -07001421 int channel = 0;
Viral Modi3a32cc52013-02-08 11:14:52 -08001422 hdd_adapter_t *pAdapter = NULL;
1423 int freq = chan->center_freq; /* freq is in MHZ */
1424
1425 ENTER();
1426
1427 if( NULL == dev )
1428 {
1429 hddLog(VOS_TRACE_LEVEL_ERROR,
1430 "%s: Called with dev = NULL.\n", __func__);
1431 return -ENODEV;
1432 }
1433 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1434
1435 hddLog(VOS_TRACE_LEVEL_INFO,
1436 "%s: device_mode = %d freq = %d \n",__func__,
1437 pAdapter->device_mode, chan->center_freq);
1438 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1439 {
1440 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1441 return -EAGAIN;
1442 }
1443
1444 /*
1445 * Do freq to chan conversion
1446 * TODO: for 11a
1447 */
1448
1449 channel = ieee80211_frequency_to_channel(freq);
1450
1451 /* Check freq range */
1452 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
1453 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
1454 {
1455 hddLog(VOS_TRACE_LEVEL_ERROR,
1456 "%s: Channel [%d] is outside valid range from %d to %d\n",
1457 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
1458 WNI_CFG_CURRENT_CHANNEL_STAMAX);
1459 return -EINVAL;
1460 }
1461
1462 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1463
Gopichand Nakkala6ab19562013-03-07 13:59:42 +05301464 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode) &&
1465 (WLAN_HDD_P2P_GO != pAdapter->device_mode))
Viral Modi3a32cc52013-02-08 11:14:52 -08001466 {
1467 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
1468 {
1469 hddLog(VOS_TRACE_LEVEL_ERROR,
1470 "%s: Invalid Channel [%d] \n", __func__, channel);
1471 return -EINVAL;
1472 }
1473 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1474 "%s: set channel to [%d] for device mode =%d",
1475 __func__, channel,pAdapter->device_mode);
1476 }
1477 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Viral Modi3a32cc52013-02-08 11:14:52 -08001478 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Viral Modi3a32cc52013-02-08 11:14:52 -08001479 )
1480 {
1481 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
1482 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
1483 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1484
1485 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
1486 {
1487 /* Link is up then return cant set channel*/
1488 hddLog( VOS_TRACE_LEVEL_ERROR,
1489 "%s: IBSS Associated, can't set the channel\n", __func__);
1490 return -EINVAL;
1491 }
1492
1493 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
1494 pHddStaCtx->conn_info.operationChannel = channel;
1495 pRoamProfile->ChannelInfo.ChannelList =
1496 &pHddStaCtx->conn_info.operationChannel;
1497 }
1498 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Viral Modi3a32cc52013-02-08 11:14:52 -08001499 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Viral Modi3a32cc52013-02-08 11:14:52 -08001500 )
1501 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301502 if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
1503 {
1504 if(VOS_STATUS_SUCCESS !=
1505 wlan_hdd_validate_operation_channel(pAdapter,channel))
1506 {
1507 hddLog(VOS_TRACE_LEVEL_ERROR,
1508 "%s: Invalid Channel [%d] \n", __func__, channel);
1509 return -EINVAL;
1510 }
1511 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1512 }
1513 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
Viral Modi3a32cc52013-02-08 11:14:52 -08001514 {
1515 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
1516
1517 /* If auto channel selection is configured as enable/ 1 then ignore
1518 channel set by supplicant
1519 */
1520 if ( cfg_param->apAutoChannelSelection )
1521 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301522 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel =
1523 AUTO_CHANNEL_SELECT;
Viral Modi3a32cc52013-02-08 11:14:52 -08001524 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1525 "%s: set channel to auto channel (0) for device mode =%d",
1526 __func__, pAdapter->device_mode);
1527 }
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301528 else
1529 {
1530 if(VOS_STATUS_SUCCESS !=
1531 wlan_hdd_validate_operation_channel(pAdapter,channel))
1532 {
1533 hddLog(VOS_TRACE_LEVEL_ERROR,
1534 "%s: Invalid Channel [%d] \n", __func__, channel);
1535 return -EINVAL;
1536 }
1537 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1538 }
Viral Modi3a32cc52013-02-08 11:14:52 -08001539 }
1540 }
1541 else
1542 {
1543 hddLog(VOS_TRACE_LEVEL_FATAL,
1544 "%s: Invalid device mode failed to set valid channel", __func__);
1545 return -EINVAL;
1546 }
1547 EXIT();
1548 return 0;
1549}
1550
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301551/*
1552 * FUNCTION: wlan_hdd_select_cbmode
1553 * called by wlan_hdd_cfg80211_start_bss() and
1554 * This function selects the cbmode based on primary channel
1555 */
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001556VOS_STATUS wlan_sap_select_cbmode(void *pAdapter,eSapPhyMode SapHw_mode, v_U8_t channel)
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301557{
1558 tSmeConfigParams smeConfig;
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001559 hdd_context_t *pHddCtx = ( hdd_context_t *) pAdapter;
1560 hdd_config_t *pConfigIni = ((hdd_context_t *)(pAdapter))->cfg_ini;
1561
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301562 if(
1563#ifdef WLAN_FEATURE_11AC
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001564 SapHw_mode != eSAP_DOT11_MODE_11ac &&
1565 SapHw_mode != eSAP_DOT11_MODE_11ac_ONLY &&
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301566#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001567 SapHw_mode != eSAP_DOT11_MODE_11n &&
1568 SapHw_mode != eSAP_DOT11_MODE_11n_ONLY
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301569 )
1570 {
1571 return VOS_STATUS_SUCCESS;
1572 }
1573
1574 if (!pConfigIni->nChannelBondingMode5GHz) {
1575 return VOS_STATUS_SUCCESS;
1576 }
1577
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001578 //channel = pSapConfig->channel;
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301579 vos_mem_zero(&smeConfig, sizeof (tSmeConfigParams));
1580
1581 sme_GetConfigParam(pHddCtx->hHal, &smeConfig);
1582
1583#ifdef WLAN_FEATURE_11AC
1584
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001585 if ( SapHw_mode == eSAP_DOT11_MODE_11ac ||
1586 SapHw_mode == eSAP_DOT11_MODE_11ac_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301587 {
1588 if ( channel== 36 || channel == 52 || channel == 100 ||
1589 channel == 116 || channel == 149 )
1590 {
1591 smeConfig.csrConfig.channelBondingMode5GHz =
1592 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW - 1;
1593 }
1594 else if ( channel == 40 || channel == 56 || channel == 104 ||
1595 channel == 120 || channel == 153 )
1596 {
1597 smeConfig.csrConfig.channelBondingMode5GHz =
1598 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW - 1;
1599 }
1600 else if ( channel == 44 || channel == 60 || channel == 108 ||
1601 channel == 124 || channel == 157 )
1602 {
1603 smeConfig.csrConfig.channelBondingMode5GHz =
1604 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH -1;
1605 }
1606 else if ( channel == 48 || channel == 64 || channel == 112 ||
1607 channel == 128 || channel == 161 )
1608 {
1609 smeConfig.csrConfig.channelBondingMode5GHz =
1610 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH - 1;
1611 }
Shailender Karmuchi84f11f02013-02-12 17:11:45 -08001612 else if ( channel == 165 )
1613 {
1614 smeConfig.csrConfig.channelBondingMode5GHz = 0;
1615 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301616 }
1617#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001618 if ( SapHw_mode == eSAP_DOT11_MODE_11n ||
1619 SapHw_mode == eSAP_DOT11_MODE_11n_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301620 {
1621 if ( channel== 40 || channel == 48 || channel == 56 ||
1622 channel == 64 || channel == 104 || channel == 112 ||
1623 channel == 120 || channel == 128 || channel == 136 ||
1624 channel == 144 || channel == 153 || channel == 161 )
1625 {
1626 smeConfig.csrConfig.channelBondingMode5GHz = 1;
1627 }
1628 else if ( channel== 36 || channel == 44 || channel == 52 ||
1629 channel == 60 || channel == 100 || channel == 108 ||
1630 channel == 116 || channel == 124 || channel == 132 ||
1631 channel == 140 || channel == 149 || channel == 157 )
1632 {
1633 smeConfig.csrConfig.channelBondingMode5GHz = 2;
1634 }
Shailender Karmuchi84f11f02013-02-12 17:11:45 -08001635 else if ( channel == 165 )
1636 {
1637 smeConfig.csrConfig.channelBondingMode5GHz = 0;
1638 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301639 }
1640 pr_info ("cbmode selected=%ld\n",smeConfig.csrConfig.channelBondingMode5GHz);
1641
1642 sme_UpdateConfig (pHddCtx->hHal,&smeConfig);
1643 return VOS_STATUS_SUCCESS;
1644}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001645
Jeff Johnson295189b2012-06-20 16:38:30 -07001646#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1647static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1648 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001649#else
1650static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1651 struct cfg80211_beacon_data *params,
1652 const u8 *ssid, size_t ssid_len,
1653 enum nl80211_hidden_ssid hidden_ssid)
1654#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001655{
1656 tsap_Config_t *pConfig;
1657 beacon_data_t *pBeacon = NULL;
1658 struct ieee80211_mgmt *pMgmt_frame;
1659 v_U8_t *pIe=NULL;
1660 v_U16_t capab_info;
1661 eCsrAuthType RSNAuthType;
1662 eCsrEncryptionType RSNEncryptType;
1663 eCsrEncryptionType mcRSNEncryptType;
1664 int status = VOS_STATUS_SUCCESS;
1665 tpWLAN_SAPEventCB pSapEventCallback;
1666 hdd_hostapd_state_t *pHostapdState;
1667 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1668 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301669 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001670 struct qc_mac_acl_entry *acl_entry = NULL;
1671 v_SINT_t i;
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001672 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001673
1674 ENTER();
1675
1676 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1677
1678 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1679
1680 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1681
1682 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1683
1684 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1685
1686 //channel is already set in the set_channel Call back
1687 //pConfig->channel = pCommitConfig->channel;
1688
1689 /*Protection parameter to enable or disable*/
1690 pConfig->protEnabled =
1691 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1692
1693 pConfig->dtim_period = pBeacon->dtim_period;
1694
1695 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1696 pConfig->dtim_period);
1697
1698
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001699 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001700 {
1701 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001702 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001703 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001704 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001705 tANI_BOOLEAN restartNeeded;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001706 pConfig->ieee80211d = 1;
1707 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1708 sme_setRegInfo(hHal, pConfig->countryCode);
1709 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
Jeff Johnson295189b2012-06-20 16:38:30 -07001710 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001711 else
1712 {
1713 pConfig->ieee80211d = 0;
1714 }
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301715 /*
1716 * If auto channel is configured i.e. channel is 0,
1717 * so skip channel validation.
1718 */
1719 if( AUTO_CHANNEL_SELECT != pConfig->channel )
1720 {
1721 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1722 {
1723 hddLog(VOS_TRACE_LEVEL_ERROR,
1724 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1725 return -EINVAL;
1726 }
1727 }
1728 else
1729 {
1730 if(1 != pHddCtx->is_dynamic_channel_range_set)
1731 {
1732 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
1733 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
1734 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
1735 }
1736 pHddCtx->is_dynamic_channel_range_set = 0;
1737 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001738 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001739 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001740 {
1741 pConfig->ieee80211d = 0;
1742 }
1743 pConfig->authType = eSAP_AUTO_SWITCH;
1744
1745 capab_info = pMgmt_frame->u.beacon.capab_info;
1746
1747 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
1748 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1749
1750 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1751
1752 /*Set wps station to configured*/
1753 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1754
1755 if(pIe)
1756 {
1757 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1758 {
1759 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1760 return -EINVAL;
1761 }
1762 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1763 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001764 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001765 /* Check 15 bit of WPS IE as it contain information for wps state
1766 * WPS state
1767 */
1768 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1769 {
1770 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1771 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1772 {
1773 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1774 }
1775 }
1776 }
1777 else
1778 {
1779 pConfig->wps_state = SAP_WPS_DISABLED;
1780 }
1781 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
1782
1783 pConfig->RSNWPAReqIELength = 0;
1784 pConfig->pRSNWPAReqIE = NULL;
1785 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1786 WLAN_EID_RSN);
1787 if(pIe && pIe[1])
1788 {
1789 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1790 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1791 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1792 /* The actual processing may eventually be more extensive than
1793 * this. Right now, just consume any PMKIDs that are sent in
1794 * by the app.
1795 * */
1796 status = hdd_softap_unpackIE(
1797 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1798 &RSNEncryptType,
1799 &mcRSNEncryptType,
1800 &RSNAuthType,
1801 pConfig->pRSNWPAReqIE[1]+2,
1802 pConfig->pRSNWPAReqIE );
1803
1804 if( VOS_STATUS_SUCCESS == status )
1805 {
1806 /* Now copy over all the security attributes you have
1807 * parsed out
1808 * */
1809 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1810 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1811 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1812 = RSNEncryptType;
1813 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1814 "EncryptionType = %d mcEncryptionType = %d\n"),
1815 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1816 }
1817 }
1818
1819 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1820 pBeacon->tail, pBeacon->tail_len);
1821
1822 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1823 {
1824 if (pConfig->pRSNWPAReqIE)
1825 {
1826 /*Mixed mode WPA/WPA2*/
1827 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1828 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1829 }
1830 else
1831 {
1832 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1833 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1834 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1835 status = hdd_softap_unpackIE(
1836 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1837 &RSNEncryptType,
1838 &mcRSNEncryptType,
1839 &RSNAuthType,
1840 pConfig->pRSNWPAReqIE[1]+2,
1841 pConfig->pRSNWPAReqIE );
1842
1843 if( VOS_STATUS_SUCCESS == status )
1844 {
1845 /* Now copy over all the security attributes you have
1846 * parsed out
1847 * */
1848 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1849 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1850 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1851 = RSNEncryptType;
1852 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1853 "EncryptionType = %d mcEncryptionType = %d\n"),
1854 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1855 }
1856 }
1857 }
1858
Jeff Johnson4416a782013-03-25 14:17:50 -07001859 if (pConfig->RSNWPAReqIELength > sizeof wpaRsnIEdata) {
1860 hddLog( VOS_TRACE_LEVEL_ERROR, "**RSNWPAReqIELength is too large***");
1861 return -EINVAL;
1862 }
1863
Jeff Johnson295189b2012-06-20 16:38:30 -07001864 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1865
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001866#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001867 if (params->ssid != NULL)
1868 {
1869 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1870 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1871 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1872 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1873 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001874#else
1875 if (ssid != NULL)
1876 {
1877 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1878 pConfig->SSIDinfo.ssid.length = ssid_len;
1879 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1880 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1881 }
1882#endif
1883
Jeff Johnson295189b2012-06-20 16:38:30 -07001884 vos_mem_copy(pConfig->self_macaddr.bytes,
1885 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1886
1887 /* default value */
1888 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1889 pConfig->num_accept_mac = 0;
1890 pConfig->num_deny_mac = 0;
1891
1892 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1893 pBeacon->tail, pBeacon->tail_len);
1894
1895 /* pIe for black list is following form:
1896 type : 1 byte
1897 length : 1 byte
1898 OUI : 4 bytes
1899 acl type : 1 byte
1900 no of mac addr in black list: 1 byte
1901 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1902 */
1903 if ((pIe != NULL) && (pIe[1] != 0))
1904 {
1905 pConfig->SapMacaddr_acl = pIe[6];
1906 pConfig->num_deny_mac = pIe[7];
1907 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1908 pIe[6], pIe[7]);
1909 if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
1910 pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
1911 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1912 for (i = 0; i < pConfig->num_deny_mac; i++)
1913 {
1914 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1915 acl_entry++;
1916 }
1917 }
1918 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1919 pBeacon->tail, pBeacon->tail_len);
1920
1921 /* pIe for white list is following form:
1922 type : 1 byte
1923 length : 1 byte
1924 OUI : 4 bytes
1925 acl type : 1 byte
1926 no of mac addr in white list: 1 byte
1927 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1928 */
1929 if ((pIe != NULL) && (pIe[1] != 0))
1930 {
1931 pConfig->SapMacaddr_acl = pIe[6];
1932 pConfig->num_accept_mac = pIe[7];
1933 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
1934 pIe[6], pIe[7]);
1935 if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
1936 pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
1937 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1938 for (i = 0; i < pConfig->num_accept_mac; i++)
1939 {
1940 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1941 acl_entry++;
1942 }
1943 }
1944 wlan_hdd_set_sapHwmode(pHostapdAdapter);
1945
Jeff Johnsone7245742012-09-05 17:12:55 -07001946#ifdef WLAN_FEATURE_11AC
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08001947 /* Overwrite the hostapd setting for HW mode only for 11ac.
1948 * This is valid only if mode is set to 11n in hostapd and either AUTO or 11ac in .ini .
1949 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode) */
1950 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
1951 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
1952 (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
1953 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1954 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07001955 {
1956 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
1957 }
1958#endif
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301959
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001960 if( AUTO_CHANNEL_SELECT != pConfig->channel)
1961 wlan_sap_select_cbmode((WLAN_HDD_GET_CTX(pHostapdAdapter)),pConfig->SapHw_mode,pConfig->channel);
Jeff Johnson295189b2012-06-20 16:38:30 -07001962 // ht_capab is not what the name conveys,this is used for protection bitmap
1963 pConfig->ht_capab =
1964 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
1965
1966 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
1967 {
1968 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
1969 return -EINVAL;
1970 }
1971
1972 //Uapsd Enabled Bit
1973 pConfig->UapsdEnable =
1974 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
1975 //Enable OBSS protection
1976 pConfig->obssProtEnabled =
1977 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
1978
1979 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
1980 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
1981 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
1982 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
1983 (int)pConfig->channel);
1984 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
1985 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
1986 pConfig->authType);
1987 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
1988 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
1989 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
1990 pConfig->protEnabled, pConfig->obssProtEnabled);
1991
1992 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
1993 {
1994 //Bss already started. just return.
1995 //TODO Probably it should update some beacon params.
1996 hddLog( LOGE, "Bss Already started...Ignore the request");
1997 EXIT();
1998 return 0;
1999 }
2000
2001 pConfig->persona = pHostapdAdapter->device_mode;
2002
2003 pSapEventCallback = hdd_hostapd_SAPEventCB;
2004 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
2005 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
2006 {
2007 hddLog(LOGE,FL("SAP Start Bss fail\n"));
2008 return -EINVAL;
2009 }
2010
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002011 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07002012 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
2013
2014 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2015
2016 if (!VOS_IS_STATUS_SUCCESS(status))
2017 {
2018 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2019 ("ERROR: HDD vos wait for single_event failed!!\n"));
2020 VOS_ASSERT(0);
2021 }
2022
2023 //Succesfully started Bss update the state bit.
2024 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
2025
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002026#ifdef WLAN_FEATURE_P2P_DEBUG
2027 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
2028 {
2029 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
2030 {
2031 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
2032 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002033 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002034 }
2035 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
2036 {
2037 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
2038 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002039 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002040 }
2041 }
2042#endif
2043
Jeff Johnson295189b2012-06-20 16:38:30 -07002044 pHostapdState->bCommit = TRUE;
2045 EXIT();
2046
2047 return 0;
2048}
2049
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002050#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002051static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
2052 struct net_device *dev,
2053 struct beacon_parameters *params)
2054{
2055 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2056 int status=VOS_STATUS_SUCCESS;
2057
2058 ENTER();
2059
2060 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
2061
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002062 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2063 {
2064 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2065 "%s:LOGP in Progress. Ignore!!!", __func__);
2066 return -EAGAIN;
2067 }
2068
Jeff Johnson295189b2012-06-20 16:38:30 -07002069 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002070 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002071 )
2072 {
2073 beacon_data_t *old,*new;
2074
2075 old = pAdapter->sessionCtx.ap.beacon;
2076
2077 if (old)
2078 return -EALREADY;
2079
2080 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2081
2082 if(status != VOS_STATUS_SUCCESS)
2083 {
2084 hddLog(VOS_TRACE_LEVEL_FATAL,
2085 "%s:Error!!! Allocating the new beacon\n",__func__);
2086 return -EINVAL;
2087 }
2088
2089 pAdapter->sessionCtx.ap.beacon = new;
2090
2091 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2092 }
2093
2094 EXIT();
2095 return status;
2096}
2097
2098static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
2099 struct net_device *dev,
2100 struct beacon_parameters *params)
2101{
2102 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2103 int status=VOS_STATUS_SUCCESS;
2104
2105 ENTER();
2106
2107 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2108 __func__,pAdapter->device_mode);
2109
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002110 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2111 {
2112 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2113 "%s:LOGP in Progress. Ignore!!!", __func__);
2114 return -EAGAIN;
2115 }
2116
Jeff Johnson295189b2012-06-20 16:38:30 -07002117 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002118 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002119 )
2120 {
2121 beacon_data_t *old,*new;
2122
2123 old = pAdapter->sessionCtx.ap.beacon;
2124
2125 if (!old)
2126 return -ENOENT;
2127
2128 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2129
2130 if(status != VOS_STATUS_SUCCESS) {
2131 hddLog(VOS_TRACE_LEVEL_FATAL,
2132 "%s: Error!!! Allocating the new beacon\n",__func__);
2133 return -EINVAL;
2134 }
2135
2136 pAdapter->sessionCtx.ap.beacon = new;
2137
2138 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2139 }
2140
2141 EXIT();
2142 return status;
2143}
2144
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002145#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
2146
2147#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002148static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
2149 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002150#else
2151static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
2152 struct net_device *dev)
2153#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002154{
2155 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07002156 hdd_context_t *pHddCtx = NULL;
2157 hdd_scaninfo_t *pScanInfo = NULL;
2158 hdd_adapter_t *staAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002159 VOS_STATUS status = 0;
2160
2161 ENTER();
2162
2163 if (NULL == pAdapter)
2164 {
2165 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002166 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002167 return -ENODEV;
2168 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002169
Jeff Johnson4416a782013-03-25 14:17:50 -07002170 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002171 if (NULL == pHddCtx)
2172 {
2173 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002174 "%s: HDD context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002175 return -ENODEV;
2176 }
Jeff Johnson4416a782013-03-25 14:17:50 -07002177 if (pHddCtx->isLogpInProgress)
2178 {
2179 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2180 "%s:LOGP in Progress. Ignore!!!", __func__);
2181 return -EAGAIN;
2182 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002183
2184 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
2185 if (NULL == staAdapter)
2186 {
2187 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
2188 if (NULL == staAdapter)
2189 {
2190 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002191 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002192 return -ENODEV;
2193 }
2194 }
2195
2196 pScanInfo = &pHddCtx->scan_info;
2197
Jeff Johnson4416a782013-03-25 14:17:50 -07002198 if (pHddCtx->isLogpInProgress)
Jeff Johnson295189b2012-06-20 16:38:30 -07002199 {
2200 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2201 return -EAGAIN;
2202 }
2203
2204 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2205
2206 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2207 __func__,pAdapter->device_mode);
2208
Jeff Johnsone7245742012-09-05 17:12:55 -07002209 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
2210 {
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002211 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Jeff Johnsone7245742012-09-05 17:12:55 -07002212 hdd_abort_mac_scan(staAdapter->pHddCtx);
2213 status = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002214 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07002215 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
2216 if (!status)
2217 {
2218 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson902c9832012-12-10 14:28:09 -08002219 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002220 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07002221 VOS_ASSERT(pScanInfo->mScanPending);
2222 return 0;
2223 }
2224 }
2225
Jeff Johnson295189b2012-06-20 16:38:30 -07002226 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002227 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002228 )
2229 {
2230 beacon_data_t *old;
2231
2232 old = pAdapter->sessionCtx.ap.beacon;
2233
2234 if (!old)
2235 return -ENOENT;
2236
Jeff Johnson295189b2012-06-20 16:38:30 -07002237 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002238
2239 mutex_lock(&pHddCtx->sap_lock);
2240 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2241 {
Jeff Johnson4416a782013-03-25 14:17:50 -07002242 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss(pHddCtx->pvosContext) ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07002243 {
2244 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2245
2246 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2247
2248 if (!VOS_IS_STATUS_SUCCESS(status))
2249 {
2250 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2251 ("ERROR: HDD vos wait for single_event failed!!\n"));
2252 VOS_ASSERT(0);
2253 }
2254 }
2255 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2256 }
2257 mutex_unlock(&pHddCtx->sap_lock);
2258
2259 if(status != VOS_STATUS_SUCCESS)
2260 {
2261 hddLog(VOS_TRACE_LEVEL_FATAL,
2262 "%s:Error!!! Stopping the BSS\n",__func__);
2263 return -EINVAL;
2264 }
2265
Jeff Johnson4416a782013-03-25 14:17:50 -07002266 if (ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002267 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
2268 ==eHAL_STATUS_FAILURE)
2269 {
2270 hddLog(LOGE,
2271 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
2272 }
2273
Jeff Johnson4416a782013-03-25 14:17:50 -07002274 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002275 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2276 eANI_BOOLEAN_FALSE) )
2277 {
2278 hddLog(LOGE,
2279 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
2280 }
2281
2282 // Reset WNI_CFG_PROBE_RSP Flags
2283 wlan_hdd_reset_prob_rspies(pAdapter);
2284
2285 pAdapter->sessionCtx.ap.beacon = NULL;
2286 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002287#ifdef WLAN_FEATURE_P2P_DEBUG
2288 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
2289 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
2290 {
2291 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
2292 "GO got removed");
2293 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
2294 }
2295#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002296 }
2297 EXIT();
2298 return status;
2299}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002300
2301#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2302
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302303static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2304 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002305 struct cfg80211_ap_settings *params)
2306{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302307 hdd_adapter_t *pAdapter;
2308 hdd_context_t *pHddCtx;
2309 int status = 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002310
2311 ENTER();
2312
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302313 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002314 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302315 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2316 "%s: Device is Null", __func__);
2317 return -ENODEV;
2318 }
2319
2320 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2321 if (NULL == pAdapter)
2322 {
2323 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2324 "%s: HDD adapter is Null", __func__);
2325 return -ENODEV;
2326 }
2327
2328 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2329 {
2330 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2331 "%s: HDD adapter magic is invalid", __func__);
2332 return -ENODEV;
2333 }
2334
2335 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2336 if (NULL == pHddCtx)
2337 {
2338 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2339 "%s: HDD context is Null", __func__);
2340 return -ENODEV;
2341 }
2342
2343 if (pHddCtx->isLogpInProgress)
2344 {
2345 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2346 "%s: LOGP in Progress. Ignore!!!", __func__);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002347 return -EAGAIN;
2348 }
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302349
2350 if (pHddCtx->isLoadUnloadInProgress)
2351 {
2352 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2353 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
2354 return -EAGAIN;
2355 }
2356
2357 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2358 __func__, pAdapter->device_mode);
2359
2360 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002361 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002362 )
2363 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302364 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002365
2366 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302367
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002368 if (old)
2369 return -EALREADY;
2370
2371 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2372
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302373 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002374 {
2375 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302376 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002377 return -EINVAL;
2378 }
2379 pAdapter->sessionCtx.ap.beacon = new;
Viral Modi3a32cc52013-02-08 11:14:52 -08002380#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2381 wlan_hdd_cfg80211_set_channel(wiphy, dev, params->channel, params->channel_type);
2382#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002383 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2384 params->ssid_len, params->hidden_ssid);
2385 }
2386
2387 EXIT();
2388 return status;
2389}
2390
2391
2392static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
2393 struct net_device *dev,
2394 struct cfg80211_beacon_data *params)
2395{
2396 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2397 int status=VOS_STATUS_SUCCESS;
2398
2399 ENTER();
2400
2401 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2402 __func__, pAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002403 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2404 {
2405 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2406 return -EAGAIN;
2407 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002408
2409 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002410 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002411 )
2412 {
2413 beacon_data_t *old,*new;
2414
2415 old = pAdapter->sessionCtx.ap.beacon;
2416
2417 if (!old)
2418 return -ENOENT;
2419
2420 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2421
2422 if(status != VOS_STATUS_SUCCESS) {
2423 hddLog(VOS_TRACE_LEVEL_FATAL,
2424 "%s: Error!!! Allocating the new beacon\n",__func__);
2425 return -EINVAL;
2426 }
2427
2428 pAdapter->sessionCtx.ap.beacon = new;
2429
2430 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2431 }
2432
2433 EXIT();
2434 return status;
2435}
2436
2437#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2438
Jeff Johnson295189b2012-06-20 16:38:30 -07002439
2440static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2441 struct net_device *dev,
2442 struct bss_parameters *params)
2443{
2444 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2445
2446 ENTER();
2447
2448 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2449 __func__,pAdapter->device_mode);
2450
2451 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002452 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002453 )
2454 {
2455 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2456 * want to update this parameter */
2457 if (-1 != params->ap_isolate)
2458 {
2459 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
2460 }
2461 }
2462
2463 EXIT();
2464 return 0;
2465}
2466
2467/*
2468 * FUNCTION: wlan_hdd_cfg80211_change_iface
2469 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2470 */
2471int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2472 struct net_device *ndev,
2473 enum nl80211_iftype type,
2474 u32 *flags,
2475 struct vif_params *params
2476 )
2477{
2478 struct wireless_dev *wdev;
2479 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2480 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002481 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002482 tCsrRoamProfile *pRoamProfile = NULL;
2483 eCsrRoamBssType LastBSSType;
2484 hdd_config_t *pConfig = pHddCtx->cfg_ini;
2485 eMib_dot11DesiredBssType connectedBssType;
2486 VOS_STATUS status;
2487
2488 ENTER();
2489
2490 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2491 {
2492 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2493 return -EAGAIN;
2494 }
2495
2496 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2497 __func__, pAdapter->device_mode);
2498
2499 wdev = ndev->ieee80211_ptr;
2500
2501#ifdef WLAN_BTAMP_FEATURE
2502 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2503 (NL80211_IFTYPE_ADHOC == type)||
2504 (NL80211_IFTYPE_AP == type)||
2505 (NL80211_IFTYPE_P2P_GO == type))
2506 {
2507 pHddCtx->isAmpAllowed = VOS_FALSE;
2508 // stop AMP traffic
2509 status = WLANBAP_StopAmp();
2510 if(VOS_STATUS_SUCCESS != status )
2511 {
2512 pHddCtx->isAmpAllowed = VOS_TRUE;
2513 hddLog(VOS_TRACE_LEVEL_FATAL,
2514 "%s: Failed to stop AMP", __func__);
2515 return -EINVAL;
2516 }
2517 }
2518#endif //WLAN_BTAMP_FEATURE
2519 /* Reset the current device mode bit mask*/
2520 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2521
2522 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07002523 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002524 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002525 )
2526 {
2527 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2528 pRoamProfile = &pWextState->roamProfile;
2529 LastBSSType = pRoamProfile->BSSType;
2530
2531 switch (type)
2532 {
2533 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002534 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002535 hddLog(VOS_TRACE_LEVEL_INFO,
2536 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2537 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002538#ifdef WLAN_FEATURE_11AC
2539 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2540 {
2541 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2542 }
2543#endif
2544 pRoamProfile->phyMode =
2545 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002546 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002547 //Check for sub-string p2p to confirm its a p2p interface
2548 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002549 {
2550 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2551 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2552 }
2553 else
2554 {
2555 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002556 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002557 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002558 break;
2559 case NL80211_IFTYPE_ADHOC:
2560 hddLog(VOS_TRACE_LEVEL_INFO,
2561 "%s: setting interface Type to ADHOC", __func__);
2562 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2563 pRoamProfile->phyMode =
2564 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
2565 wdev->iftype = type;
2566 break;
2567
2568 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002569 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002570 {
2571 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2572 "%s: setting interface Type to %s", __func__,
2573 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2574
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002575 //Cancel any remain on channel for GO mode
2576 if (NL80211_IFTYPE_P2P_GO == type)
2577 {
2578 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2579 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002580 if (NL80211_IFTYPE_AP == type)
2581 {
2582 /* As Loading WLAN Driver one interface being created for p2p device
2583 * address. This will take one HW STA and the max number of clients
2584 * that can connect to softAP will be reduced by one. so while changing
2585 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2586 * interface as it is not required in SoftAP mode.
2587 */
2588
2589 // Get P2P Adapter
2590 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2591
2592 if (pP2pAdapter)
2593 {
2594 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2595 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2596 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2597 }
2598 }
2599
Jeff Johnson295189b2012-06-20 16:38:30 -07002600 //De-init the adapter.
2601 hdd_stop_adapter( pHddCtx, pAdapter );
2602 hdd_deinit_adapter( pHddCtx, pAdapter );
2603 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
Jeff Johnson295189b2012-06-20 16:38:30 -07002604 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2605 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002606
2607 //Disable BMPS and IMPS if enabled
2608 //before starting Go
2609 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2610 {
2611 if(VOS_STATUS_E_FAILURE ==
2612 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2613 {
2614 //Fail to Exit BMPS
2615 VOS_ASSERT(0);
2616 }
2617 }
2618
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002619 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2620 (pConfig->apRandomBssidEnabled))
2621 {
2622 /* To meet Android requirements create a randomized
2623 MAC address of the form 02:1A:11:Fx:xx:xx */
2624 get_random_bytes(&ndev->dev_addr[3], 3);
2625 ndev->dev_addr[0] = 0x02;
2626 ndev->dev_addr[1] = 0x1A;
2627 ndev->dev_addr[2] = 0x11;
2628 ndev->dev_addr[3] |= 0xF0;
2629 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2630 VOS_MAC_ADDR_SIZE);
2631 pr_info("wlan: Generated HotSpot BSSID "
2632 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2633 ndev->dev_addr[0],
2634 ndev->dev_addr[1],
2635 ndev->dev_addr[2],
2636 ndev->dev_addr[3],
2637 ndev->dev_addr[4],
2638 ndev->dev_addr[5]);
2639 }
2640
Jeff Johnson295189b2012-06-20 16:38:30 -07002641 hdd_set_ap_ops( pAdapter->dev );
2642
2643 status = hdd_init_ap_mode(pAdapter);
2644 if(status != VOS_STATUS_SUCCESS)
2645 {
2646 hddLog(VOS_TRACE_LEVEL_FATAL,
2647 "%s: Error initializing the ap mode", __func__);
2648 return -EINVAL;
2649 }
2650 hdd_set_conparam(1);
2651
Jeff Johnson295189b2012-06-20 16:38:30 -07002652 /*interface type changed update in wiphy structure*/
2653 if(wdev)
2654 {
2655 wdev->iftype = type;
2656 pHddCtx->change_iface = type;
2657 }
2658 else
2659 {
2660 hddLog(VOS_TRACE_LEVEL_ERROR,
2661 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2662 return -EINVAL;
2663 }
2664 goto done;
2665 }
2666
2667 default:
2668 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2669 __func__);
2670 return -EOPNOTSUPP;
2671 }
2672 }
2673 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002674 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002675 )
2676 {
2677 switch(type)
2678 {
2679 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002680 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002681 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002682 hdd_stop_adapter( pHddCtx, pAdapter );
2683 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002684 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002685 //Check for sub-string p2p to confirm its a p2p interface
2686 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002687 {
2688 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2689 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2690 }
2691 else
2692 {
2693 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002694 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002695 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002696 hdd_set_conparam(0);
2697 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002698 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2699 hdd_set_station_ops( pAdapter->dev );
2700 status = hdd_init_station_mode( pAdapter );
2701 if( VOS_STATUS_SUCCESS != status )
2702 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002703 /* In case of JB, for P2P-GO, only change interface will be called,
2704 * This is the right place to enable back bmps_imps()
2705 */
2706 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002707 goto done;
2708 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002709 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002710 wdev->iftype = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002711 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2712 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07002713 goto done;
2714 default:
2715 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2716 __func__);
2717 return -EOPNOTSUPP;
2718
2719 }
2720
2721 }
2722 else
2723 {
2724 return -EOPNOTSUPP;
2725 }
2726
2727
2728 if(pRoamProfile)
2729 {
2730 if ( LastBSSType != pRoamProfile->BSSType )
2731 {
2732 /*interface type changed update in wiphy structure*/
2733 wdev->iftype = type;
2734
2735 /*the BSS mode changed, We need to issue disconnect
2736 if connected or in IBSS disconnect state*/
2737 if ( hdd_connGetConnectedBssType(
2738 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2739 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2740 {
2741 /*need to issue a disconnect to CSR.*/
2742 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2743 if( eHAL_STATUS_SUCCESS ==
2744 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2745 pAdapter->sessionId,
2746 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2747 {
2748 wait_for_completion_interruptible_timeout(
2749 &pAdapter->disconnect_comp_var,
2750 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2751 }
2752 }
2753 }
2754 }
2755
2756done:
2757 /*set bitmask based on updated value*/
2758 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
2759#ifdef WLAN_BTAMP_FEATURE
2760 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
2761 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2762 {
2763 //we are ok to do AMP
2764 pHddCtx->isAmpAllowed = VOS_TRUE;
2765 }
2766#endif //WLAN_BTAMP_FEATURE
2767 EXIT();
2768 return 0;
2769}
2770
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002771#ifdef FEATURE_WLAN_TDLS
2772static int wlan_hdd_tdls_add_station(struct wiphy *wiphy,
2773 struct net_device *dev, u8 *mac, bool update, tCsrStaParams *StaParams)
2774{
2775 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2776 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2777 VOS_STATUS status;
2778
2779 ENTER();
2780
Jeff Johnsond75fe012013-04-06 10:53:06 -07002781 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini || NULL == StaParams)
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002782 {
2783 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2784 "Invalid arguments");
2785 return -EINVAL;
2786 }
Hoonki Lee27511902013-03-14 18:19:06 -07002787
2788 if ((eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) ||
2789 (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode))
2790 {
2791 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2792 "%s: TDLS mode is disabled OR not enabled in FW."
2793 MAC_ADDRESS_STR " Request declined.",
2794 __func__, MAC_ADDR_ARRAY(mac));
2795 return -ENOTSUPP;
2796 }
2797
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002798 if (pHddCtx->isLogpInProgress)
2799 {
2800 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2801 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07002802 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002803 return -EBUSY;
2804 }
2805
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002806 /* when self is on-going, we dont' want to change link_status */
2807 if ((0 == update) && wlan_hdd_tdls_is_peer_progress(pAdapter, mac))
2808 {
2809 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2810 "%s: " MAC_ADDRESS_STR
2811 " TDLS setup is ongoing. Request declined.",
2812 __func__, MAC_ADDR_ARRAY(mac));
2813 return -EPERM;
2814 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002815 /* when self is not on-ongoing, we don't want to allow change_station */
2816 if ((1 == update) && !wlan_hdd_tdls_is_peer_progress(pAdapter, mac))
2817 {
2818 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2819 "%s: " MAC_ADDRESS_STR
2820 " TDLS is not connecting. change station declined.",
2821 __func__, MAC_ADDR_ARRAY(mac));
2822 return -EPERM;
2823 }
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002824
2825 /* when others are on-going, we want to change link_status to idle */
2826 if (wlan_hdd_tdls_is_progress(pAdapter, mac, TRUE))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002827 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002828 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2829 "%s: " MAC_ADDRESS_STR
2830 " TDLS setup is ongoing. Request declined.",
2831 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002832 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002833 }
2834
2835 /* first to check if we reached to maximum supported TDLS peer.
2836 TODO: for now, return -EPERM looks working fine,
2837 but need to check if any other errno fit into this category.*/
2838 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
2839 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002840 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2841 "%s: " MAC_ADDRESS_STR
2842 " TDLS Max peer already connected. Request declined.",
2843 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002844 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002845 }
2846 else
2847 {
2848 hddTdlsPeer_t *pTdlsPeer;
2849 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002850 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002851 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002852 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2853 "%s: " MAC_ADDRESS_STR " already connected. Request declined.",
2854 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002855 return -EPERM;
2856 }
2857 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002858 if (0 == update)
2859 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_CONNECTING);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002860
Jeff Johnsond75fe012013-04-06 10:53:06 -07002861 /* debug code */
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002862 {
2863 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2864 "%s: TDLS Peer Parameters.", __func__);
2865 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2866 "ht_capa->cap_info: %0x", StaParams->HTCap.capInfo);
2867 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2868 "ht_capa->extended_capabilities: %0x",
2869 StaParams->HTCap.extendedHtCapInfo);
2870 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2871 "params->capability: %0x",StaParams->capability);
2872 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2873 "params->ext_capab_len: %0x",StaParams->extn_capability);
2874 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2875 "rxMcsMap %x rxHighest %x txMcsMap %x txHighest %x",
2876 StaParams->VHTCap.suppMcs.rxMcsMap, StaParams->VHTCap.suppMcs.rxHighest,
2877 StaParams->VHTCap.suppMcs.txMcsMap, StaParams->VHTCap.suppMcs.txHighest);
2878 {
2879 int i = 0;
2880 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "Supported rates:");
2881 for (i = 0; i < sizeof(StaParams->supported_rates); i++)
2882 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2883 "[%d]: %x ", i, StaParams->supported_rates[i]);
2884 }
Jeff Johnsond75fe012013-04-06 10:53:06 -07002885 } /* end debug code */
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002886
2887 INIT_COMPLETION(pAdapter->tdls_add_station_comp);
2888
2889 if (!update)
2890 {
2891 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
2892 pAdapter->sessionId, mac);
2893 }
2894 else
2895 {
2896 status = sme_ChangeTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
2897 pAdapter->sessionId, mac, StaParams);
2898 }
2899
2900 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_add_station_comp,
2901 msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
2902
2903 if (!status)
2904 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002905 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002906 "%s: timeout waiting for tdls add station indication",
2907 __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002908 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002909 }
2910 if ( eHAL_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus)
2911 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002912 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002913 "%s: Add Station is unsucessful", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002914 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002915 }
2916
2917 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07002918
2919error:
2920 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
2921 return -EPERM;
2922
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002923}
2924#endif
2925
Jeff Johnson295189b2012-06-20 16:38:30 -07002926static int wlan_hdd_change_station(struct wiphy *wiphy,
2927 struct net_device *dev,
2928 u8 *mac,
2929 struct station_parameters *params)
2930{
2931 VOS_STATUS status = VOS_STATUS_SUCCESS;
2932 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2933 v_MACADDR_t STAMacAddress;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002934#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002935 tCsrStaParams StaParams = {0};
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002936 tANI_U8 isBufSta = 0;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002937#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07002938 ENTER();
2939
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002940 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2941 {
2942 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2943 "%s:LOGP in Progress. Ignore!!!", __func__);
2944 return -EAGAIN;
2945 }
2946
Jeff Johnson295189b2012-06-20 16:38:30 -07002947 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
2948
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002949 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2950 || (pAdapter->device_mode == WLAN_HDD_P2P_GO))
Jeff Johnson295189b2012-06-20 16:38:30 -07002951 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002952 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
Jeff Johnson295189b2012-06-20 16:38:30 -07002953 {
2954 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
2955 WLANTL_STA_AUTHENTICATED);
2956
2957 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002958 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002959 return -EINVAL;
2960 }
2961 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002962#ifdef FEATURE_WLAN_TDLS
Hoonki Leea6d49be2013-04-05 09:43:25 -07002963 else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2964 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) {
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002965 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
2966 StaParams.capability = params->capability;
2967 StaParams.uapsd_queues = params->uapsd_queues;
2968 StaParams.max_sp = params->max_sp;
2969
2970 if (0 != params->ext_capab_len)
2971 vos_mem_copy(StaParams.extn_capability, params->ext_capab,
2972 sizeof(StaParams.extn_capability));
2973
2974 if (NULL != params->ht_capa)
2975 vos_mem_copy(&StaParams.HTCap, params->ht_capa, sizeof(tSirHTCap));
2976
2977 StaParams.supported_rates_len = params->supported_rates_len;
2978
2979 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
2980 * The supported_rates array , for all the structures propogating till Add Sta
2981 * to the firmware has to be modified , if the supplicant (ieee80211) is
2982 * modified to send more rates.
2983 */
2984
2985 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
2986 */
2987 if (StaParams.supported_rates_len > SIR_MAC_MAX_SUPP_RATES)
2988 StaParams.supported_rates_len = SIR_MAC_MAX_SUPP_RATES;
2989
2990 if (0 != StaParams.supported_rates_len) {
2991 int i = 0;
2992 vos_mem_copy(StaParams.supported_rates, params->supported_rates,
2993 StaParams.supported_rates_len);
2994 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2995 "Supported Rates with Length %d", StaParams.supported_rates_len);
2996 for (i=0; i < StaParams.supported_rates_len; i++)
2997 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2998 "[%d]: %0x", i, StaParams.supported_rates[i]);
2999 }
3000
3001 if (NULL != params->vht_capa)
3002 vos_mem_copy(&StaParams.VHTCap, params->vht_capa, sizeof(tSirVHTCap));
3003
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003004 if (0 != params->ext_capab_len ) {
3005 /*Define A Macro : TODO Sunil*/
3006 if ((1<<4) & StaParams.extn_capability[3]) {
3007 isBufSta = 1;
3008 }
3009 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003010 //status = wlan_hdd_tdls_set_peer_caps( mac, params->uapsd_queues,
3011 // params->max_sp, isBufSta);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003012 //if (VOS_STATUS_SUCCESS != status) {
3013 // VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3014 // "%s: wlan_hdd_tdls_set_peer_caps failed!", __func__);
3015 // return -EINVAL;
3016 //}
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003017 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 1, &StaParams);
3018
3019 if (VOS_STATUS_SUCCESS != status) {
3020 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3021 "%s: sme_ChangeTdlsPeerSta failed!", __func__);
3022 return -EINVAL;
3023 }
3024 }
3025 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003026#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003027
Jeff Johnsone7245742012-09-05 17:12:55 -07003028 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003029 return status;
3030}
3031
3032/*
3033 * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
3034 * This function is used to get peer station index in IBSS mode
3035 */
3036static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
3037{
3038 u8 idx = 0;
3039 u8 temp[VOS_MAC_ADDR_SIZE] = {0};
3040 ENTER();
3041 memset(temp, 0, VOS_MAC_ADDR_SIZE);
3042 for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
3043 {
3044 if ( (0 !=
3045 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
3046 && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
3047 temp, VOS_MAC_ADDR_SIZE)
3048 )
3049 {
3050 return idx;
3051 }
3052 }
3053 return idx;
3054}
3055
3056
3057/*
3058 * FUNCTION: wlan_hdd_cfg80211_add_key
3059 * This function is used to initialize the key information
3060 */
3061#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003062static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003063 struct net_device *ndev,
3064 u8 key_index, bool pairwise,
3065 const u8 *mac_addr,
3066 struct key_params *params
3067 )
3068#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003069static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003070 struct net_device *ndev,
3071 u8 key_index, const u8 *mac_addr,
3072 struct key_params *params
3073 )
3074#endif
3075{
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003076 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003077 tCsrRoamSetKey setKey;
3078 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3079 int status = 0;
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003080 v_U32_t roamId= 0xFF;
3081 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003082 hdd_hostapd_state_t *pHostapdState;
3083 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003084 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07003085
3086 ENTER();
3087
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003088 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3089 {
3090 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3091 "%s:LOGP in Progress. Ignore!!!", __func__);
3092 return -EAGAIN;
3093 }
3094
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003095 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
3096 __func__, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003097
3098 if (CSR_MAX_NUM_KEY <= key_index)
3099 {
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003100 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003101 key_index);
3102
3103 return -EINVAL;
3104 }
3105
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003106 if (CSR_MAX_KEY_LEN < params->key_len)
3107 {
3108 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key length %d", __func__,
3109 params->key_len);
3110
3111 return -EINVAL;
3112 }
3113
3114 hddLog(VOS_TRACE_LEVEL_INFO,
3115 "%s: called with key index = %d & key length %d",
3116 __func__, key_index, params->key_len);
Jeff Johnson295189b2012-06-20 16:38:30 -07003117
3118 /*extract key idx, key len and key*/
3119 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3120 setKey.keyId = key_index;
3121 setKey.keyLength = params->key_len;
3122 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
3123
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003124 switch (params->cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07003125 {
3126 case WLAN_CIPHER_SUITE_WEP40:
3127 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
3128 break;
3129
3130 case WLAN_CIPHER_SUITE_WEP104:
3131 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
3132 break;
3133
3134 case WLAN_CIPHER_SUITE_TKIP:
3135 {
3136 u8 *pKey = &setKey.Key[0];
3137 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
3138
3139 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
3140
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003141 /*Supplicant sends the 32bytes key in this order
Jeff Johnson295189b2012-06-20 16:38:30 -07003142
3143 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003144 | Tk1 |TX-MIC | RX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003145 |--------------|----------|----------|
3146 <---16bytes---><--8bytes--><--8bytes-->
3147
3148 */
3149 /*Sme expects the 32 bytes key to be in the below order
3150
3151 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003152 | Tk1 |RX-MIC | TX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003153 |--------------|----------|----------|
3154 <---16bytes---><--8bytes--><--8bytes-->
3155 */
3156 /* Copy the Temporal Key 1 (TK1) */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003157 vos_mem_copy(pKey, params->key, 16);
Jeff Johnson295189b2012-06-20 16:38:30 -07003158
3159 /*Copy the rx mic first*/
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003160 vos_mem_copy(&pKey[16], &params->key[24], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003161
3162 /*Copy the tx mic */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003163 vos_mem_copy(&pKey[24], &params->key[16], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003164
3165
3166 break;
3167 }
3168
3169 case WLAN_CIPHER_SUITE_CCMP:
3170 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
3171 break;
3172
3173#ifdef FEATURE_WLAN_WAPI
3174 case WLAN_CIPHER_SUITE_SMS4:
3175 {
3176 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3177 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
3178 params->key, params->key_len);
3179 return 0;
3180 }
3181#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003182
Jeff Johnson295189b2012-06-20 16:38:30 -07003183#ifdef FEATURE_WLAN_CCX
3184 case WLAN_CIPHER_SUITE_KRK:
3185 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
3186 break;
3187#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003188
3189#ifdef WLAN_FEATURE_11W
3190 case WLAN_CIPHER_SUITE_AES_CMAC:
3191 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
Chet Lanctot3b5158a2013-03-31 16:45:21 -07003192 break;
Chet Lanctot186b5732013-03-18 10:26:30 -07003193#endif
3194
Jeff Johnson295189b2012-06-20 16:38:30 -07003195 default:
3196 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
3197 __func__, params->cipher);
3198 return -EOPNOTSUPP;
3199 }
3200
3201 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
3202 __func__, setKey.encType);
3203
3204
3205
3206 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003207 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07003208 )
3209 {
3210
3211
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003212 if (
Jeff Johnson295189b2012-06-20 16:38:30 -07003213#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3214 (!pairwise)
3215#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003216 (!mac_addr || is_broadcast_ether_addr(mac_addr))
Jeff Johnson295189b2012-06-20 16:38:30 -07003217#endif
3218 )
3219 {
3220 /* set group key*/
3221 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson1250df42012-12-10 14:31:52 -08003222 "%s- %d: setting Broadcast key",
Jeff Johnson295189b2012-06-20 16:38:30 -07003223 __func__, __LINE__);
3224 setKey.keyDirection = eSIR_RX_ONLY;
3225 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3226 }
3227 else
3228 {
3229 /* set pairwise key*/
3230 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3231 "%s- %d: setting pairwise key",
3232 __func__, __LINE__);
3233 setKey.keyDirection = eSIR_TX_RX;
3234 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3235 }
3236
3237 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003238 if( pHostapdState->bssState == BSS_START )
3239 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003240 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3241
3242 if ( status != eHAL_STATUS_SUCCESS )
3243 {
3244 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3245 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3246 __LINE__, status );
3247 }
3248 }
3249
3250 /* Saving WEP keys */
3251 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
3252 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
3253 {
3254 //Save the wep key in ap context. Issue setkey after the BSS is started.
3255 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3256 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
3257 }
3258 else
3259 {
3260 //Save the key in ap context. Issue setkey after the BSS is started.
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003261 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003262 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
3263 }
3264 }
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003265 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
3266 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) )
Jeff Johnson295189b2012-06-20 16:38:30 -07003267 {
3268 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3269 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3270
3271 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
3272
Venkata Prathyusha Kuntupalliee2ce712013-01-17 14:09:24 -08003273 pWextState->roamProfile.Keys.defaultIndex = key_index;
3274
3275
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003276 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07003277 params->key, params->key_len);
3278
3279 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3280
3281 if (!( ( IW_AUTH_KEY_MGMT_802_1X
3282 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
3283 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3284 )
3285 &&
3286 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3287 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3288 )
3289 )
3290 {
3291 /* in case of static WEP, macaddr/bssid is not coming from nl80211
3292 * interface, copy bssid for pairwise key and group macaddr for
3293 * group key initialization*/
3294
3295 tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
3296
3297 pWextState->roamProfile.negotiatedUCEncryptionType =
3298 pHddStaCtx->conn_info.ucEncryptionType =
3299 ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
3300 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
3301 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
3302
3303
3304 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3305 "%s: Negotiated encryption type %d", __func__,
3306 pWextState->roamProfile.negotiatedUCEncryptionType);
3307
3308 sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
3309 &pWextState->roamProfile, true);
3310 setKey.keyLength = 0;
3311 setKey.keyDirection = eSIR_TX_RX;
3312
3313#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3314 if (pairwise)
3315 {
3316#endif
3317 if (mac_addr)
3318 {
3319 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3320 }
3321 else
3322 {
3323 /* macaddr is NULL, set the peerMac to bssId in case of BSS,
3324 * and peerMacAddress in case of IBSS*/
3325 if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
3326 {
3327 u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
3328 if (HDD_MAX_NUM_IBSS_STA != staidx)
3329 {
3330 vos_mem_copy(setKey.peerMac,
3331 &pHddStaCtx->conn_info.peerMacAddress[staidx],
3332 WNI_CFG_BSSID_LEN);
3333
3334 }
3335 else
3336 {
3337 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
3338 __func__);
3339 return -EOPNOTSUPP;
3340 }
3341 }
3342 else
3343 {
3344 vos_mem_copy(setKey.peerMac,
3345 &pHddStaCtx->conn_info.bssId[0],
3346 WNI_CFG_BSSID_LEN);
3347 }
3348 }
3349#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3350 }
3351 else
3352 {
3353 /* set group key*/
3354 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3355 "%s- %d: setting Group key",
3356 __func__, __LINE__);
3357 setKey.keyDirection = eSIR_RX_ONLY;
3358 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3359 }
3360#endif
3361 }
3362 else if (
3363#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3364 (!pairwise)
3365#else
3366 (!mac_addr || is_broadcast_ether_addr(mac_addr))
3367#endif
3368 )
3369 {
3370 /* set group key*/
3371 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3372 "%s- %d: setting Group key",
3373 __func__, __LINE__);
3374 setKey.keyDirection = eSIR_RX_ONLY;
3375 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3376 }
3377 else
3378 {
3379 /* set pairwise key*/
3380 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3381 "%s- %d: setting pairwise key",
3382 __func__, __LINE__);
3383 setKey.keyDirection = eSIR_TX_RX;
3384 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3385 }
3386
3387 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3388 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3389 __func__, setKey.peerMac[0], setKey.peerMac[1],
3390 setKey.peerMac[2], setKey.peerMac[3],
3391 setKey.peerMac[4], setKey.peerMac[5],
3392 setKey.keyDirection);
3393
3394 vos_status = wlan_hdd_check_ula_done(pAdapter);
3395
3396 if ( vos_status != VOS_STATUS_SUCCESS )
3397 {
3398 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3399 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
3400 __LINE__, vos_status );
3401
3402 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3403
3404 return -EINVAL;
3405
3406 }
3407
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003408#ifdef WLAN_FEATURE_VOWIFI_11R
3409 /* The supplicant may attempt to set the PTK once pre-authentication is done.
3410 Save the key in the UMAC and include it in the ADD BSS request */
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003411 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303412 if( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_WAIT )
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003413 {
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303414 return -EINVAL;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003415 }
3416#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07003417
3418 /* issue set key request to SME*/
3419 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3420 pAdapter->sessionId, &setKey, &roamId );
3421
3422 if ( 0 != status )
3423 {
3424 hddLog(VOS_TRACE_LEVEL_ERROR,
3425 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3426 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3427 return -EINVAL;
3428 }
3429
3430
3431 /* in case of IBSS as there was no information available about WEP keys during
3432 * IBSS join, group key intialized with NULL key, so re-initialize group key
3433 * with correct value*/
3434 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
3435 !( ( IW_AUTH_KEY_MGMT_802_1X
3436 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
3437 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3438 )
3439 &&
3440 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3441 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3442 )
3443 )
3444 {
3445 setKey.keyDirection = eSIR_RX_ONLY;
3446 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3447
3448 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3449 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3450 __func__, setKey.peerMac[0], setKey.peerMac[1],
3451 setKey.peerMac[2], setKey.peerMac[3],
3452 setKey.peerMac[4], setKey.peerMac[5],
3453 setKey.keyDirection);
3454
3455 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3456 pAdapter->sessionId, &setKey, &roamId );
3457
3458 if ( 0 != status )
3459 {
3460 hddLog(VOS_TRACE_LEVEL_ERROR,
3461 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
3462 __func__, status);
3463 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3464 return -EINVAL;
3465 }
3466 }
3467 }
3468
3469 return 0;
3470}
3471
3472/*
3473 * FUNCTION: wlan_hdd_cfg80211_get_key
3474 * This function is used to get the key information
3475 */
3476#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3477static int wlan_hdd_cfg80211_get_key(
3478 struct wiphy *wiphy,
3479 struct net_device *ndev,
3480 u8 key_index, bool pairwise,
3481 const u8 *mac_addr, void *cookie,
3482 void (*callback)(void *cookie, struct key_params*)
3483 )
3484#else
3485static int wlan_hdd_cfg80211_get_key(
3486 struct wiphy *wiphy,
3487 struct net_device *ndev,
3488 u8 key_index, const u8 *mac_addr, void *cookie,
3489 void (*callback)(void *cookie, struct key_params*)
3490 )
3491#endif
3492{
3493 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3494 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3495 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
3496 struct key_params params;
3497
3498 ENTER();
3499
3500 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3501 __func__,pAdapter->device_mode);
3502
3503 memset(&params, 0, sizeof(params));
3504
3505 if (CSR_MAX_NUM_KEY <= key_index)
3506 {
3507 return -EINVAL;
3508 }
3509
3510 switch(pRoamProfile->EncryptionType.encryptionType[0])
3511 {
3512 case eCSR_ENCRYPT_TYPE_NONE:
3513 params.cipher = IW_AUTH_CIPHER_NONE;
3514 break;
3515
3516 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3517 case eCSR_ENCRYPT_TYPE_WEP40:
3518 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3519 break;
3520
3521 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3522 case eCSR_ENCRYPT_TYPE_WEP104:
3523 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3524 break;
3525
3526 case eCSR_ENCRYPT_TYPE_TKIP:
3527 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3528 break;
3529
3530 case eCSR_ENCRYPT_TYPE_AES:
3531 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3532 break;
3533
3534 default:
3535 params.cipher = IW_AUTH_CIPHER_NONE;
3536 break;
3537 }
3538
3539 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3540 params.seq_len = 0;
3541 params.seq = NULL;
3542 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3543 callback(cookie, &params);
3544 return 0;
3545}
3546
3547/*
3548 * FUNCTION: wlan_hdd_cfg80211_del_key
3549 * This function is used to delete the key information
3550 */
3551#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3552static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3553 struct net_device *ndev,
3554 u8 key_index,
3555 bool pairwise,
3556 const u8 *mac_addr
3557 )
3558#else
3559static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3560 struct net_device *ndev,
3561 u8 key_index,
3562 const u8 *mac_addr
3563 )
3564#endif
3565{
3566 int status = 0;
3567
3568 //This code needs to be revisited. There is sme_removeKey API, we should
3569 //plan to use that. After the change to use correct index in setkey,
3570 //it is observed that this is invalidating peer
3571 //key index whenever re-key is done. This is affecting data link.
3572 //It should be ok to ignore del_key.
3573#if 0
3574 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3575 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
3576 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3577 tCsrRoamSetKey setKey;
3578 v_U32_t roamId= 0xFF;
3579
3580 ENTER();
3581
3582 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3583 __func__,pAdapter->device_mode);
3584
3585 if (CSR_MAX_NUM_KEY <= key_index)
3586 {
3587 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3588 key_index);
3589
3590 return -EINVAL;
3591 }
3592
3593 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3594 setKey.keyId = key_index;
3595
3596 if (mac_addr)
3597 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3598 else
3599 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3600
3601 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3602
3603 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003604 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07003605 )
3606 {
3607
3608 hdd_hostapd_state_t *pHostapdState =
3609 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3610 if( pHostapdState->bssState == BSS_START)
3611 {
3612 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3613
3614 if ( status != eHAL_STATUS_SUCCESS )
3615 {
3616 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3617 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3618 __LINE__, status );
3619 }
3620 }
3621 }
3622 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003623 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003624 )
3625 {
3626 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3627
3628 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3629
3630 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3631 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
3632 __func__, setKey.peerMac[0], setKey.peerMac[1],
3633 setKey.peerMac[2], setKey.peerMac[3],
3634 setKey.peerMac[4], setKey.peerMac[5]);
3635 if(pAdapter->sessionCtx.station.conn_info.connState ==
3636 eConnectionState_Associated)
3637 {
3638 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3639 pAdapter->sessionId, &setKey, &roamId );
3640
3641 if ( 0 != status )
3642 {
3643 hddLog(VOS_TRACE_LEVEL_ERROR,
3644 "%s: sme_RoamSetKey failure, returned %d",
3645 __func__, status);
3646 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3647 return -EINVAL;
3648 }
3649 }
3650 }
3651#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003652 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003653 return status;
3654}
3655
3656/*
3657 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3658 * This function is used to set the default tx key index
3659 */
3660#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3661static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3662 struct net_device *ndev,
3663 u8 key_index,
3664 bool unicast, bool multicast)
3665#else
3666static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3667 struct net_device *ndev,
3668 u8 key_index)
3669#endif
3670{
3671 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3672 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3673 int status = 0;
3674 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3675
3676 ENTER();
3677
3678 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3679 __func__,pAdapter->device_mode, key_index);
3680
3681 if (CSR_MAX_NUM_KEY <= key_index)
3682 {
3683 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3684 key_index);
3685
3686 return -EINVAL;
3687 }
3688
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003689 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3690 {
3691 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3692 "%s:LOGP in Progress. Ignore!!!", __func__);
3693 return -EAGAIN;
3694 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003695
3696 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003697 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003698 )
3699 {
3700 if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
3701 (eCSR_ENCRYPT_TYPE_TKIP !=
3702 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3703 (eCSR_ENCRYPT_TYPE_AES !=
3704 pWextState->roamProfile.EncryptionType.encryptionType[0])
3705 )
3706 {
3707 /* if default key index is not same as previous one,
3708 * then update the default key index */
3709
3710 tCsrRoamSetKey setKey;
3711 v_U32_t roamId= 0xFF;
3712 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
3713
3714 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
3715 __func__, key_index);
3716
3717 Keys->defaultIndex = (u8)key_index;
3718 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3719 setKey.keyId = key_index;
3720 setKey.keyLength = Keys->KeyLength[key_index];
3721
3722 vos_mem_copy(&setKey.Key[0],
3723 &Keys->KeyMaterial[key_index][0],
3724 Keys->KeyLength[key_index]);
3725
3726 setKey.keyDirection = eSIR_TX_ONLY;
3727
3728 vos_mem_copy(setKey.peerMac,
3729 &pHddStaCtx->conn_info.bssId[0],
3730 WNI_CFG_BSSID_LEN);
3731
3732 setKey.encType =
3733 pWextState->roamProfile.EncryptionType.encryptionType[0];
3734
3735 /* issue set key request */
3736 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3737 pAdapter->sessionId, &setKey, &roamId );
3738
3739 if ( 0 != status )
3740 {
3741 hddLog(VOS_TRACE_LEVEL_ERROR,
3742 "%s: sme_RoamSetKey failed, returned %d", __func__,
3743 status);
3744 return -EINVAL;
3745 }
3746 }
3747 }
3748
3749 /* In SoftAp mode setting key direction for default mode */
3750 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3751 {
3752 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3753 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3754 (eCSR_ENCRYPT_TYPE_AES !=
3755 pWextState->roamProfile.EncryptionType.encryptionType[0])
3756 )
3757 {
3758 /* Saving key direction for default key index to TX default */
3759 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3760 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3761 }
3762 }
3763
3764 return status;
3765}
3766
Jeff Johnson295189b2012-06-20 16:38:30 -07003767/*
3768 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3769 * This function is used to inform the BSS details to nl80211 interface.
3770 */
3771static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3772 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3773{
3774 struct net_device *dev = pAdapter->dev;
3775 struct wireless_dev *wdev = dev->ieee80211_ptr;
3776 struct wiphy *wiphy = wdev->wiphy;
3777 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3778 int chan_no;
3779 int ie_length;
3780 const char *ie;
3781 unsigned int freq;
3782 struct ieee80211_channel *chan;
3783 int rssi = 0;
3784 struct cfg80211_bss *bss = NULL;
3785
3786 ENTER();
3787
3788 if( NULL == pBssDesc )
3789 {
3790 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3791 return bss;
3792 }
3793
3794 chan_no = pBssDesc->channelId;
3795 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3796 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3797
3798 if( NULL == ie )
3799 {
3800 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3801 return bss;
3802 }
3803
3804#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3805 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3806 {
3807 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3808 }
3809 else
3810 {
3811 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3812 }
3813#else
3814 freq = ieee80211_channel_to_frequency(chan_no);
3815#endif
3816
3817 chan = __ieee80211_get_channel(wiphy, freq);
3818
3819 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3820 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3821 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3822 if (bss == NULL)
3823 {
3824 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3825
3826 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3827 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3828 pBssDesc->capabilityInfo,
3829 pBssDesc->beaconInterval, ie, ie_length,
3830 rssi, GFP_KERNEL ));
3831}
3832 else
3833 {
3834 return bss;
3835 }
3836}
3837
3838
3839
3840/*
3841 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3842 * This function is used to inform the BSS details to nl80211 interface.
3843 */
3844struct cfg80211_bss*
3845wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3846 tSirBssDescription *bss_desc
3847 )
3848{
3849 /*
3850 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3851 already exists in bss data base of cfg80211 for that particular BSS ID.
3852 Using cfg80211_inform_bss_frame to update the bss entry instead of
3853 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3854 now there is no possibility to get the mgmt(probe response) frame from PE,
3855 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3856 cfg80211_inform_bss_frame.
3857 */
3858 struct net_device *dev = pAdapter->dev;
3859 struct wireless_dev *wdev = dev->ieee80211_ptr;
3860 struct wiphy *wiphy = wdev->wiphy;
3861 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003862#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3863 qcom_ie_age *qie_age = NULL;
3864 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3865#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003866 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003867#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003868 const char *ie =
3869 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3870 unsigned int freq;
3871 struct ieee80211_channel *chan;
3872 struct ieee80211_mgmt *mgmt =
3873 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3874 struct cfg80211_bss *bss_status = NULL;
3875 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3876 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003877#ifdef WLAN_OPEN_SOURCE
3878 struct timespec ts;
3879#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003880
3881 ENTER();
3882
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003883 if (!mgmt)
3884 return NULL;
3885
Jeff Johnson295189b2012-06-20 16:38:30 -07003886 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003887
3888#ifdef WLAN_OPEN_SOURCE
3889 /* Android does not want the timestamp from the frame.
3890 Instead it wants a monotonic increasing value */
3891 get_monotonic_boottime(&ts);
3892 mgmt->u.probe_resp.timestamp =
3893 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3894#else
3895 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003896 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3897 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003898
3899#endif
3900
Jeff Johnson295189b2012-06-20 16:38:30 -07003901 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3902 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003903
3904#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3905 /* GPS Requirement: need age ie per entry. Using vendor specific. */
3906 /* Assuming this is the last IE, copy at the end */
3907 ie_length -=sizeof(qcom_ie_age);
3908 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
3909 qie_age->element_id = QCOM_VENDOR_IE_ID;
3910 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
3911 qie_age->oui_1 = QCOM_OUI1;
3912 qie_age->oui_2 = QCOM_OUI2;
3913 qie_age->oui_3 = QCOM_OUI3;
3914 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
3915 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
3916#endif
3917
Jeff Johnson295189b2012-06-20 16:38:30 -07003918 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3919
3920 mgmt->frame_control |=
3921 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3922
3923#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3924 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3925 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3926 {
3927 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3928 }
3929 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3930 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3931
3932 {
3933 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3934 }
3935 else
3936 {
3937 kfree(mgmt);
3938 return NULL;
3939 }
3940#else
3941 freq = ieee80211_channel_to_frequency(chan_no);
3942#endif
3943 chan = __ieee80211_get_channel(wiphy, freq);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08003944 /*when the band is changed on the fly using the GUI, three things are done
3945 * 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)
3946 * as part of the scan abort, message willbe queued to PE and we proceed with flushing and changinh the band.
3947 * pe will stop the scanning further and report back the results what ever it had till now by calling the call back function.
3948 * if the time between update band and scandone call back is sufficent enough the band change reflects in SME, SME validates the channels
3949 * and discards the channels correponding to previous band and calls back with zero bss results.
3950 * 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
3951 * all the channels correponding to previous band.this is due to race condition.but those channels are invalid to the new band and so
3952 * this function __ieee80211_get_channel will return NULL.Each time we report scan result with this pointer null warning kernel trace is printed.
3953 * if the scan results contain large number of APs continuosly kernel warning trace is printed and it will lead to apps watch dog bark.
3954 * So drop the bss and continue to next bss.
3955 */
3956 if(chan == NULL)
3957 {
3958 hddLog(VOS_TRACE_LEVEL_INFO, "%s chan pointer is NULL", __func__);
Chilam Ngc4244af2013-04-01 15:37:32 -07003959 kfree(mgmt);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08003960 return NULL;
3961 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003962 /*To keep the rssi icon of the connected AP in the scan window
3963 *and the rssi icon of the wireless networks in sync
3964 * */
3965 if (( eConnectionState_Associated ==
3966 pAdapter->sessionCtx.station.conn_info.connState ) &&
3967 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3968 pAdapter->sessionCtx.station.conn_info.bssId,
3969 WNI_CFG_BSSID_LEN)))
3970 {
3971 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3972 rssi = (pAdapter->rssi * 100);
3973 }
3974 else
3975 {
3976 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3977 }
3978
3979 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3980 frame_len, rssi, GFP_KERNEL);
3981 kfree(mgmt);
3982 return bss_status;
3983}
3984
3985/*
3986 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3987 * This function is used to update the BSS data base of CFG8011
3988 */
3989struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3990 tCsrRoamInfo *pRoamInfo
3991 )
3992{
3993 tCsrRoamConnectedProfile roamProfile;
3994 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3995 struct cfg80211_bss *bss = NULL;
3996
3997 ENTER();
3998
3999 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
4000 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
4001
4002 if (NULL != roamProfile.pBssDesc)
4003 {
4004 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
4005 &roamProfile);
4006
4007 if (NULL == bss)
4008 {
4009 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
4010 __func__);
4011 }
4012
4013 sme_RoamFreeConnectProfile(hHal, &roamProfile);
4014 }
4015 else
4016 {
4017 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
4018 __func__);
4019 }
4020 return bss;
4021}
4022
4023/*
4024 * FUNCTION: wlan_hdd_cfg80211_update_bss
4025 */
4026static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
4027 hdd_adapter_t *pAdapter
4028 )
4029{
4030 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4031 tCsrScanResultInfo *pScanResult;
4032 eHalStatus status = 0;
4033 tScanResultHandle pResult;
4034 struct cfg80211_bss *bss_status = NULL;
4035
4036 ENTER();
4037
4038 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4039 {
4040 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
4041 return -EAGAIN;
4042 }
4043
4044 /*
4045 * start getting scan results and populate cgf80211 BSS database
4046 */
4047 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
4048
4049 /* no scan results */
4050 if (NULL == pResult)
4051 {
4052 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
4053 return status;
4054 }
4055
4056 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
4057
4058 while (pScanResult)
4059 {
4060 /*
4061 * cfg80211_inform_bss() is not updating ie field of bss entry, if
4062 * entry already exists in bss data base of cfg80211 for that
4063 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
4064 * bss entry instead of cfg80211_inform_bss, But this call expects
4065 * mgmt packet as input. As of now there is no possibility to get
4066 * the mgmt(probe response) frame from PE, converting bss_desc to
4067 * ieee80211_mgmt(probe response) and passing to c
4068 * fg80211_inform_bss_frame.
4069 * */
4070
4071 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
4072 &pScanResult->BssDescriptor);
4073
4074
4075 if (NULL == bss_status)
4076 {
4077 hddLog(VOS_TRACE_LEVEL_INFO,
4078 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
4079 }
4080 else
4081 {
4082 cfg80211_put_bss(bss_status);
4083 }
4084
4085 pScanResult = sme_ScanResultGetNext(hHal, pResult);
4086 }
4087
4088 sme_ScanResultPurge(hHal, pResult);
4089
4090 return 0;
4091}
4092
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004093void
4094hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
4095{
4096 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004097 "%02X:%02X:%02X:%02X:%02X:%02X\n",
4098 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
4099 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004100} /****** end hddPrintMacAddr() ******/
4101
4102void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004103hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004104{
4105 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004106 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
4107 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
4108 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
4109 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004110} /****** end hddPrintPmkId() ******/
4111
4112//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
4113//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
4114
4115//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
4116//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
4117
4118#define dump_bssid(bssid) \
4119 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004120 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
4121 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
4122 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004123 }
4124
4125#define dump_pmkid(pMac, pmkid) \
4126 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004127 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
4128 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
4129 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004130 }
4131
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07004132#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004133/*
4134 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
4135 * This function is used to notify the supplicant of a new PMKSA candidate.
4136 */
4137int wlan_hdd_cfg80211_pmksa_candidate_notify(
4138 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
4139 int index, bool preauth )
4140{
Jeff Johnsone7245742012-09-05 17:12:55 -07004141#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004142 struct net_device *dev = pAdapter->dev;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004143 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004144
4145 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07004146 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004147
4148 if( NULL == pRoamInfo )
4149 {
4150 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
4151 return -EINVAL;
4152 }
4153
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004154 if (eANI_BOOLEAN_TRUE == hdd_is_okc_mode_enabled(pHddCtx))
4155 {
4156 dump_bssid(pRoamInfo->bssid);
4157 cfg80211_pmksa_candidate_notify(dev, index,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004158 pRoamInfo->bssid, preauth, GFP_KERNEL);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004159 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004160#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004161 return 0;
4162}
4163#endif //FEATURE_WLAN_LFR
4164
Jeff Johnson295189b2012-06-20 16:38:30 -07004165/*
4166 * FUNCTION: hdd_cfg80211_scan_done_callback
4167 * scanning callback function, called after finishing scan
4168 *
4169 */
4170static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
4171 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
4172{
4173 struct net_device *dev = (struct net_device *) pContext;
4174 //struct wireless_dev *wdev = dev->ieee80211_ptr;
4175 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004176 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4177 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004178 struct cfg80211_scan_request *req = NULL;
4179 int ret = 0;
4180
4181 ENTER();
4182
4183 hddLog(VOS_TRACE_LEVEL_INFO,
4184 "%s called with halHandle = %p, pContext = %p,"
4185 "scanID = %d, returned status = %d\n",
4186 __func__, halHandle, pContext, (int) scanId, (int) status);
4187
4188 //Block on scan req completion variable. Can't wait forever though.
4189 ret = wait_for_completion_interruptible_timeout(
4190 &pScanInfo->scan_req_completion_event,
4191 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
4192 if (!ret)
4193 {
4194 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004195 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004196 }
4197
4198 if(pScanInfo->mScanPending != VOS_TRUE)
4199 {
4200 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004201 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004202 }
4203
4204 /* Check the scanId */
4205 if (pScanInfo->scanId != scanId)
4206 {
4207 hddLog(VOS_TRACE_LEVEL_INFO,
4208 "%s called with mismatched scanId pScanInfo->scanId = %d "
4209 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
4210 (int) scanId);
4211 }
4212
Jeff Johnson295189b2012-06-20 16:38:30 -07004213 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
4214 pAdapter);
4215
4216 if (0 > ret)
4217 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
4218
4219
4220 /* If any client wait scan result through WEXT
4221 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004222 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07004223 {
4224 /* The other scan request waiting for current scan finish
4225 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004226 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004227 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004228 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004229 }
4230 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004231 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004232 {
4233 struct net_device *dev = pAdapter->dev;
4234 union iwreq_data wrqu;
4235 int we_event;
4236 char *msg;
4237
4238 memset(&wrqu, '\0', sizeof(wrqu));
4239 we_event = SIOCGIWSCAN;
4240 msg = NULL;
4241 wireless_send_event(dev, we_event, &wrqu, msg);
4242 }
4243 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004244 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004245
4246 /* Get the Scan Req */
4247 req = pAdapter->request;
4248
4249 if (!req)
4250 {
4251 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004252 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07004253 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004254 }
4255
4256 /*
4257 * setting up 0, just in case.
4258 */
4259 req->n_ssids = 0;
4260 req->n_channels = 0;
4261 req->ie = 0;
4262
Jeff Johnson295189b2012-06-20 16:38:30 -07004263 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004264 /* Scan is no longer pending */
4265 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004266
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07004267 /*
4268 * cfg80211_scan_done informing NL80211 about completion
4269 * of scanning
4270 */
4271 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004272 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004273
Jeff Johnsone7245742012-09-05 17:12:55 -07004274allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004275 /* release the wake lock at the end of the scan*/
4276 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004277
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004278 /* Acquire wakelock to handle the case where APP's tries to suspend
4279 * immediatly after the driver gets connect request(i.e after scan)
4280 * from supplicant, this result in app's is suspending and not able
4281 * to process the connect request to AP */
4282 hdd_allow_suspend_timeout(100);
4283
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004284#ifdef FEATURE_WLAN_TDLS
4285 wlan_hdd_tdls_scan_done_callback(pAdapter);
4286#endif
4287
Jeff Johnson295189b2012-06-20 16:38:30 -07004288 EXIT();
4289 return 0;
4290}
4291
4292/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004293 * FUNCTION: hdd_isScanAllowed
4294 * Go through each adapter and check if scan allowed
4295 *
4296 */
4297v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
4298{
4299 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4300 hdd_station_ctx_t *pHddStaCtx = NULL;
4301 hdd_adapter_t *pAdapter = NULL;
4302 VOS_STATUS status = 0;
4303 v_U8_t staId = 0;
4304 v_U8_t *staMac = NULL;
4305
4306 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4307
4308 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4309 {
4310 pAdapter = pAdapterNode->pAdapter;
4311
4312 if( pAdapter )
4313 {
4314 hddLog(VOS_TRACE_LEVEL_INFO,
4315 "%s: Adapter with device mode %d exists",
4316 __func__, pAdapter->device_mode);
4317 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4318 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4319 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
4320 {
4321 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4322 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
4323 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
4324 {
4325 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
4326 hddLog(VOS_TRACE_LEVEL_ERROR,
4327 "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the "
4328 "middle of WPS/EAPOL exchange.", __func__,
4329 staMac[0], staMac[1], staMac[2],
4330 staMac[3], staMac[4], staMac[5]);
4331 return VOS_FALSE;
4332 }
4333 }
4334 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
4335 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
4336 {
4337 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
4338 {
4339 if ((pAdapter->aStaInfo[staId].isUsed) &&
4340 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
4341 {
4342 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
4343
4344 hddLog(VOS_TRACE_LEVEL_ERROR,
4345 "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the "
4346 "middle of WPS/EAPOL exchange.", __func__,
4347 staMac[0], staMac[1], staMac[2],
4348 staMac[3], staMac[4], staMac[5]);
4349 return VOS_FALSE;
4350 }
4351 }
4352 }
4353 }
4354 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4355 pAdapterNode = pNext;
4356 }
4357 hddLog(VOS_TRACE_LEVEL_INFO,
4358 "%s: Scan allowed", __func__);
4359 return VOS_TRUE;
4360}
4361
4362/*
Jeff Johnson295189b2012-06-20 16:38:30 -07004363 * FUNCTION: wlan_hdd_cfg80211_scan
4364 * this scan respond to scan trigger and update cfg80211 scan database
4365 * later, scan dump command can be used to recieve scan results
4366 */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08004367int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
4368#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4369 struct net_device *dev,
4370#endif
4371 struct cfg80211_scan_request *request)
4372{
4373#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4374 struct net_device *dev = request->wdev->netdev;
4375#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004376 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4377 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4378 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4379 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
4380 tCsrScanRequest scanRequest;
4381 tANI_U8 *channelList = NULL, i;
4382 v_U32_t scanId = 0;
4383 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004384 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004385 v_U8_t* pP2pIe = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004386
4387 ENTER();
4388
4389 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4390 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004391
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004392 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004393 (eConnectionState_Connecting ==
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004394 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004395 {
4396 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004397 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
4398 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004399 return -EBUSY;
4400 }
4401
Jeff Johnson295189b2012-06-20 16:38:30 -07004402#ifdef WLAN_BTAMP_FEATURE
4403 //Scan not supported when AMP traffic is on.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004404 if (VOS_TRUE == WLANBAP_AmpSessionOn())
Jeff Johnson295189b2012-06-20 16:38:30 -07004405 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004406 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004407 "%s: No scanning when AMP is on", __func__);
4408 return -EOPNOTSUPP;
4409 }
4410#endif
4411 //Scan on any other interface is not supported.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004412 if (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07004413 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004414 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004415 "%s: Not scanning on device_mode = %d",
4416 __func__, pAdapter->device_mode);
4417 return -EOPNOTSUPP;
4418 }
4419
4420 if (TRUE == pScanInfo->mScanPending)
4421 {
4422 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004423 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07004424 }
4425
4426 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4427 {
4428 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4429 "%s:LOGP in Progress. Ignore!!!", __func__);
4430 return -EAGAIN;
4431 }
4432
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07004433 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
4434 {
4435 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4436 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
4437 return -EAGAIN;
4438 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004439 //Don't Allow Scan and return busy if Remain On
4440 //Channel and action frame is pending
4441 //Otherwise Cancel Remain On Channel and allow Scan
4442 //If no action frame pending
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004443 if (0 != wlan_hdd_check_remain_on_channel(pAdapter))
Jeff Johnson32d95a32012-09-10 13:15:23 -07004444 {
4445 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
4446 return -EBUSY;
4447 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004448#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004449 /* if tdls disagree scan right now, return immediately.
4450 tdls will schedule the scan when scan is allowed. (return SUCCESS)
4451 or will reject the scan if any TDLS is in progress. (return -EBUSY)
4452 */
4453 status = wlan_hdd_tdls_scan_callback (pAdapter,
4454 wiphy,
4455#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4456 dev,
Gopichand Nakkalac3c42b92013-03-20 19:42:34 -07004457#endif
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004458 request);
4459 if(status <= 0)
4460 {
4461 hddLog(VOS_TRACE_LEVEL_INFO, "%s: TDLS Pending %d", __func__, status);
4462 return status;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004463 }
4464#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07004465
Jeff Johnson295189b2012-06-20 16:38:30 -07004466 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
4467 {
4468 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08004469 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004470 return -EAGAIN;
4471 }
4472 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
4473 {
4474 hddLog(VOS_TRACE_LEVEL_WARN,
4475 "%s: MAX TM Level Scan not allowed", __func__);
4476 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4477 return -EBUSY;
4478 }
4479 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4480
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004481 /* Check if scan is allowed at this point of time.
4482 */
4483 if (!hdd_isScanAllowed(pHddCtx))
4484 {
4485 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
4486 return -EBUSY;
4487 }
4488
Jeff Johnson295189b2012-06-20 16:38:30 -07004489 vos_mem_zero( &scanRequest, sizeof(scanRequest));
4490
4491 if (NULL != request)
4492 {
4493 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
4494 (int)request->n_ssids);
4495
4496 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
4497 * Becasue of this, driver is assuming that this is not wildcard scan and so
4498 * is not aging out the scan results.
4499 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07004500 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07004501 {
4502 request->n_ssids = 0;
4503 }
4504
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004505 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07004506 {
4507 tCsrSSIDInfo *SsidInfo;
4508 int j;
4509 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
4510 /* Allocate num_ssid tCsrSSIDInfo structure */
4511 SsidInfo = scanRequest.SSIDs.SSIDList =
4512 ( tCsrSSIDInfo *)vos_mem_malloc(
4513 request->n_ssids*sizeof(tCsrSSIDInfo));
4514
4515 if(NULL == scanRequest.SSIDs.SSIDList)
4516 {
4517 hddLog(VOS_TRACE_LEVEL_ERROR,
4518 "memory alloc failed SSIDInfo buffer");
4519 return -ENOMEM;
4520 }
4521
4522 /* copy all the ssid's and their length */
4523 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
4524 {
4525 /* get the ssid length */
4526 SsidInfo->SSID.length = request->ssids[j].ssid_len;
4527 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
4528 SsidInfo->SSID.length);
4529 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
4530 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
4531 j, SsidInfo->SSID.ssId);
4532 }
4533 /* set the scan type to active */
4534 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4535 }
4536 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4537 {
4538 /* set the scan type to active */
4539 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4540 }
4541 else
4542 {
4543 /*Set the scan type to default type, in this case it is ACTIVE*/
4544 scanRequest.scanType = pScanInfo->scan_mode;
4545 }
4546 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
4547 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4548 }
4549 else
4550 {
4551 /* set the scan type to active */
4552 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4553 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4554
4555 /* set min and max channel time to zero */
4556 scanRequest.minChnTime = 0;
4557 scanRequest.maxChnTime = 0;
4558 }
4559
4560 /* set BSSType to default type */
4561 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4562
4563 /*TODO: scan the requested channels only*/
4564
4565 /*Right now scanning all the channels */
4566 if( request )
4567 {
4568 if( request->n_channels )
4569 {
4570 channelList = vos_mem_malloc( request->n_channels );
4571 if( NULL == channelList )
4572 {
4573 status = -ENOMEM;
4574 goto free_mem;
4575 }
4576
4577 for( i = 0 ; i < request->n_channels ; i++ )
4578 channelList[i] = request->channels[i]->hw_value;
4579 }
4580
4581 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4582 scanRequest.ChannelInfo.ChannelList = channelList;
4583
4584 /* set requestType to full scan */
4585 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004586
4587 /* Flush the scan results(only p2p beacons) for STA scan and P2P
4588 * search (Flush on both full scan and social scan but not on single
4589 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
4590 */
4591
4592 /* Supplicant does single channel scan after 8-way handshake
4593 * and in that case driver shoudnt flush scan results. If
4594 * driver flushes the scan results here and unfortunately if
4595 * the AP doesnt respond to our probe req then association
4596 * fails which is not desired
4597 */
4598
4599 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4600 {
4601 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4602 pAdapter->sessionId );
4603 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004604
4605 if( request->ie_len )
4606 {
4607 /* save this for future association (join requires this) */
4608 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4609 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4610 pScanInfo->scanAddIE.length = request->ie_len;
4611
4612 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004613 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4614 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004615 )
4616 {
4617 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4618 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4619 }
4620
4621 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4622 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4623
Jeff Johnson295189b2012-06-20 16:38:30 -07004624 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4625 request->ie_len);
4626 if (pP2pIe != NULL)
4627 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004628#ifdef WLAN_FEATURE_P2P_DEBUG
4629 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4630 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4631 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4632 {
4633 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4634 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4635 "Go nego completed to Connection is started");
4636 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4637 "for 8way Handshake");
4638 }
4639 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4640 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4641 {
4642 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4643 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4644 "Disconnected state to Connection is started");
4645 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4646 "for 4way Handshake");
4647 }
4648#endif
4649
Jeff Johnsone7245742012-09-05 17:12:55 -07004650 /* no_cck will be set during p2p find to disable 11b rates */
4651 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004652 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004653 hddLog(VOS_TRACE_LEVEL_INFO,
4654 "%s: This is a P2P Search", __func__);
4655 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004656
Jeff Johnsone7245742012-09-05 17:12:55 -07004657 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4658 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004659 /* set requestType to P2P Discovery */
4660 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004661 }
4662
4663 /*
4664 Skip Dfs Channel in case of P2P Search
4665 if it is set in ini file
4666 */
4667 if(cfg_param->skipDfsChnlInP2pSearch)
4668 {
4669 scanRequest.skipDfsChnlInP2pSearch = 1;
4670 }
4671 else
4672 {
4673 scanRequest.skipDfsChnlInP2pSearch = 0;
4674 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004675
Jeff Johnson295189b2012-06-20 16:38:30 -07004676 }
4677 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004678 }
4679 }
4680
4681 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4682
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004683 /* acquire the wakelock to avoid the apps suspend during the scan. To
4684 * address the following issues.
4685 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4686 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4687 * for long time, this result in apps running at full power for long time.
4688 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4689 * be stuck in full power because of resume BMPS
4690 */
4691 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004692
4693 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004694 pAdapter->sessionId, &scanRequest, &scanId,
4695 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004696
Jeff Johnson295189b2012-06-20 16:38:30 -07004697 if (eHAL_STATUS_SUCCESS != status)
4698 {
4699 hddLog(VOS_TRACE_LEVEL_ERROR,
4700 "%s: sme_ScanRequest returned error %d", __func__, status);
4701 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004702 if(eHAL_STATUS_RESOURCES == status)
4703 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004704 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 -07004705 status = -EBUSY;
4706 } else {
4707 status = -EIO;
4708 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004709 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004710 goto free_mem;
4711 }
4712
4713 pScanInfo->mScanPending = TRUE;
4714 pAdapter->request = request;
4715 pScanInfo->scanId = scanId;
4716
4717 complete(&pScanInfo->scan_req_completion_event);
4718
4719free_mem:
4720 if( scanRequest.SSIDs.SSIDList )
4721 {
4722 vos_mem_free(scanRequest.SSIDs.SSIDList);
4723 }
4724
4725 if( channelList )
4726 vos_mem_free( channelList );
4727
4728 EXIT();
4729
4730 return status;
4731}
4732
4733/*
4734 * FUNCTION: wlan_hdd_cfg80211_connect_start
4735 * This function is used to start the association process
4736 */
4737int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004738 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004739{
4740 int status = 0;
4741 hdd_wext_state_t *pWextState;
4742 v_U32_t roamId;
4743 tCsrRoamProfile *pRoamProfile;
4744 eMib_dot11DesiredBssType connectedBssType;
4745 eCsrAuthType RSNAuthType;
4746
4747 ENTER();
4748
4749 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4750
4751 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4752 {
4753 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4754 return -EINVAL;
4755 }
4756
4757 pRoamProfile = &pWextState->roamProfile;
4758
4759 if (pRoamProfile)
4760 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004761 int ret = 0;
4762 hdd_station_ctx_t *pHddStaCtx;
4763 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4764 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4765
4766 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4767 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4768 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004769 {
4770 /* Issue disconnect to CSR */
4771 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4772 if( eHAL_STATUS_SUCCESS ==
4773 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4774 pAdapter->sessionId,
4775 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4776 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004777 ret = wait_for_completion_interruptible_timeout(
4778 &pAdapter->disconnect_comp_var,
4779 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4780 if (0 == ret)
4781 {
4782 VOS_ASSERT(0);
4783 }
4784 }
4785 }
4786 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4787 {
4788 ret = wait_for_completion_interruptible_timeout(
4789 &pAdapter->disconnect_comp_var,
4790 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4791 if (0 == ret)
4792 {
4793 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004794 }
4795 }
4796
4797 if (HDD_WMM_USER_MODE_NO_QOS ==
4798 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4799 {
4800 /*QoS not enabled in cfg file*/
4801 pRoamProfile->uapsd_mask = 0;
4802 }
4803 else
4804 {
4805 /*QoS enabled, update uapsd mask from cfg file*/
4806 pRoamProfile->uapsd_mask =
4807 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4808 }
4809
4810 pRoamProfile->SSIDs.numOfSSIDs = 1;
4811 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4812 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
4813 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
4814 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4815 ssid, ssid_len);
4816
4817 if (bssid)
4818 {
4819 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4820 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4821 WNI_CFG_BSSID_LEN);
4822 /* Save BSSID in seperate variable as well, as RoamProfile
4823 BSSID is getting zeroed out in the association process. And in
4824 case of join failure we should send valid BSSID to supplicant
4825 */
4826 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4827 WNI_CFG_BSSID_LEN);
4828 }
4829
4830 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4831 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4832 {
4833 /*set gen ie*/
4834 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4835 /*set auth*/
4836 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4837 }
4838 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4839 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4840 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4841 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4842 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4843 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4844 )
4845 {
4846 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4847 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4848 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4849 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4850 eCSR_AUTH_TYPE_AUTOSWITCH;
4851 pWextState->roamProfile.AuthType.authType[0] =
4852 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4853 }
4854#ifdef FEATURE_WLAN_WAPI
4855 if (pAdapter->wapi_info.nWapiMode)
4856 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004857 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004858 switch (pAdapter->wapi_info.wapiAuthMode)
4859 {
4860 case WAPI_AUTH_MODE_PSK:
4861 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004862 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004863 pAdapter->wapi_info.wapiAuthMode);
4864 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4865 break;
4866 }
4867 case WAPI_AUTH_MODE_CERT:
4868 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004869 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004870 pAdapter->wapi_info.wapiAuthMode);
4871 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4872 break;
4873 }
4874 } // End of switch
4875 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4876 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4877 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004878 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004879 pRoamProfile->AuthType.numEntries = 1;
4880 pRoamProfile->EncryptionType.numEntries = 1;
4881 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4882 pRoamProfile->mcEncryptionType.numEntries = 1;
4883 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4884 }
4885 }
4886#endif /* FEATURE_WLAN_WAPI */
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05304887#ifdef WLAN_FEATURE_GTK_OFFLOAD
4888 /* Initializing gtkOffloadRequestParams */
4889 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4890 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4891 {
4892 pHddStaCtx->gtkOffloadRequestParams.requested = FALSE;
4893 memset(&pHddStaCtx->gtkOffloadRequestParams.gtkOffloadReqParams,
4894 0, sizeof (tSirGtkOffloadParams));
4895 }
4896#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004897 pRoamProfile->csrPersona = pAdapter->device_mode;
4898
Jeff Johnson32d95a32012-09-10 13:15:23 -07004899 if( operatingChannel )
4900 {
4901 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4902 pRoamProfile->ChannelInfo.numOfChannels = 1;
4903 }
Chet Lanctot186b5732013-03-18 10:26:30 -07004904 else
4905 {
4906 pRoamProfile->ChannelInfo.ChannelList = NULL;
4907 pRoamProfile->ChannelInfo.numOfChannels = 0;
4908 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004909
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004910 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
4911 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
4912 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
4913 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004914 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
4915 */
4916 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4917 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
4918 eConnectionState_Connecting);
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004919
Jeff Johnson295189b2012-06-20 16:38:30 -07004920 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4921 pAdapter->sessionId, pRoamProfile, &roamId);
4922
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004923 if( (eHAL_STATUS_SUCCESS != status) &&
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304924 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
4925
4926 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004927 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
4928 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
4929 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304930 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004931 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304932 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004933
4934 pRoamProfile->ChannelInfo.ChannelList = NULL;
4935 pRoamProfile->ChannelInfo.numOfChannels = 0;
4936
Jeff Johnson295189b2012-06-20 16:38:30 -07004937 }
4938 else
4939 {
4940 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4941 return -EINVAL;
4942 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004943 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004944 return status;
4945}
4946
4947/*
4948 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4949 * This function is used to set the authentication type (OPEN/SHARED).
4950 *
4951 */
4952static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4953 enum nl80211_auth_type auth_type)
4954{
4955 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4956 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4957
4958 ENTER();
4959
4960 /*set authentication type*/
4961 switch (auth_type)
4962 {
4963 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4964 case NL80211_AUTHTYPE_AUTOMATIC:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07004965#ifdef WLAN_FEATURE_VOWIFI_11R
4966 case NL80211_AUTHTYPE_FT:
4967#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07004968 hddLog(VOS_TRACE_LEVEL_INFO,
4969 "%s: set authentication type to OPEN", __func__);
4970 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4971 break;
4972
4973 case NL80211_AUTHTYPE_SHARED_KEY:
4974 hddLog(VOS_TRACE_LEVEL_INFO,
4975 "%s: set authentication type to SHARED", __func__);
4976 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4977 break;
4978#ifdef FEATURE_WLAN_CCX
4979 case NL80211_AUTHTYPE_NETWORK_EAP:
4980 hddLog(VOS_TRACE_LEVEL_INFO,
4981 "%s: set authentication type to CCKM WPA", __func__);
4982 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4983 break;
4984#endif
4985
4986
4987 default:
4988 hddLog(VOS_TRACE_LEVEL_ERROR,
4989 "%s: Unsupported authentication type %d", __func__,
4990 auth_type);
4991 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4992 return -EINVAL;
4993 }
4994
4995 pWextState->roamProfile.AuthType.authType[0] =
4996 pHddStaCtx->conn_info.authType;
4997 return 0;
4998}
4999
5000/*
5001 * FUNCTION: wlan_hdd_set_akm_suite
5002 * This function is used to set the key mgmt type(PSK/8021x).
5003 *
5004 */
5005static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
5006 u32 key_mgmt
5007 )
5008{
5009 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5010 ENTER();
5011
5012 /*set key mgmt type*/
5013 switch(key_mgmt)
5014 {
5015 case WLAN_AKM_SUITE_PSK:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05305016#ifdef WLAN_FEATURE_VOWIFI_11R
5017 case WLAN_AKM_SUITE_FT_PSK:
5018#endif
5019 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
Jeff Johnson295189b2012-06-20 16:38:30 -07005020 __func__);
5021 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
5022 break;
5023
5024 case WLAN_AKM_SUITE_8021X:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05305025#ifdef WLAN_FEATURE_VOWIFI_11R
5026 case WLAN_AKM_SUITE_FT_8021X:
5027#endif
5028 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
Jeff Johnson295189b2012-06-20 16:38:30 -07005029 __func__);
5030 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
5031 break;
5032#ifdef FEATURE_WLAN_CCX
5033#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
5034#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
5035 case WLAN_AKM_SUITE_CCKM:
5036 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
5037 __func__);
5038 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
5039 break;
5040#endif
5041
5042 default:
5043 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
5044 __func__, key_mgmt);
5045 return -EINVAL;
5046
5047 }
5048 return 0;
5049}
5050
5051/*
5052 * FUNCTION: wlan_hdd_cfg80211_set_cipher
5053 * This function is used to set the encryption type
5054 * (NONE/WEP40/WEP104/TKIP/CCMP).
5055 */
5056static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
5057 u32 cipher,
5058 bool ucast
5059 )
5060{
5061 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5062 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5063 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5064
5065 ENTER();
5066
5067 if (!cipher)
5068 {
5069 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
5070 __func__, cipher);
5071 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5072 }
5073 else
5074 {
5075
5076 /*set encryption method*/
5077 switch (cipher)
5078 {
5079 case IW_AUTH_CIPHER_NONE:
5080 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5081 break;
5082
5083 case WLAN_CIPHER_SUITE_WEP40:
5084 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
5085 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
5086 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
5087 else
5088 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5089 break;
5090
5091 case WLAN_CIPHER_SUITE_WEP104:
5092 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
5093 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
5094 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
5095 else
5096 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
5097 break;
5098
5099 case WLAN_CIPHER_SUITE_TKIP:
5100 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5101 break;
5102
5103 case WLAN_CIPHER_SUITE_CCMP:
5104 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5105 break;
5106#ifdef FEATURE_WLAN_WAPI
5107 case WLAN_CIPHER_SUITE_SMS4:
5108 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
5109 break;
5110#endif
5111
5112#ifdef FEATURE_WLAN_CCX
5113 case WLAN_CIPHER_SUITE_KRK:
5114 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
5115 break;
5116#endif
5117 default:
5118 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
5119 __func__, cipher);
5120 return -EOPNOTSUPP;
5121 }
5122 }
5123
5124 if (ucast)
5125 {
5126 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
5127 __func__, encryptionType);
5128 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5129 pWextState->roamProfile.EncryptionType.numEntries = 1;
5130 pWextState->roamProfile.EncryptionType.encryptionType[0] =
5131 encryptionType;
5132 }
5133 else
5134 {
5135 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
5136 __func__, encryptionType);
5137 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
5138 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
5139 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
5140 }
5141
5142 return 0;
5143}
5144
5145
5146/*
5147 * FUNCTION: wlan_hdd_cfg80211_set_ie
5148 * This function is used to parse WPA/RSN IE's.
5149 */
5150int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
5151 u8 *ie,
5152 size_t ie_len
5153 )
5154{
5155 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5156 u8 *genie = ie;
5157 v_U16_t remLen = ie_len;
5158#ifdef FEATURE_WLAN_WAPI
5159 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
5160 u16 *tmp;
5161 v_U16_t akmsuiteCount;
5162 int *akmlist;
5163#endif
5164 ENTER();
5165
5166 /* clear previous assocAddIE */
5167 pWextState->assocAddIE.length = 0;
5168 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
5169
5170 while (remLen >= 2)
5171 {
5172 v_U16_t eLen = 0;
5173 v_U8_t elementId;
5174 elementId = *genie++;
5175 eLen = *genie++;
5176 remLen -= 2;
5177
5178 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
5179 __func__, elementId, eLen);
5180
5181 switch ( elementId )
5182 {
5183 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005184 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 -07005185 {
5186 hddLog(VOS_TRACE_LEVEL_ERROR,
5187 "%s: Invalid WPA IE", __func__);
5188 return -EINVAL;
5189 }
5190 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
5191 {
5192 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5193 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
5194 __func__, eLen + 2);
5195
5196 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5197 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005198 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
5199 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005200 VOS_ASSERT(0);
5201 return -ENOMEM;
5202 }
5203 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5204 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5205 pWextState->assocAddIE.length += eLen + 2;
5206
5207 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
5208 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5209 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5210 }
5211 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
5212 {
5213 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
5214 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5215 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
5216 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
5217 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
5218 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005219 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
5220 P2P_OUI_TYPE_SIZE))
5221 /*Consider P2P IE, only for P2P Client */
5222 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5223 {
5224 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5225 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
5226 __func__, eLen + 2);
5227
5228 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5229 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005230 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5231 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005232 VOS_ASSERT(0);
5233 return -ENOMEM;
5234 }
5235 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5236 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5237 pWextState->assocAddIE.length += eLen + 2;
5238
5239 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5240 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5241 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005242#ifdef WLAN_FEATURE_WFD
5243 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
5244 WFD_OUI_TYPE_SIZE))
5245 /*Consider WFD IE, only for P2P Client */
5246 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5247 {
5248 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5249 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
5250 __func__, eLen + 2);
5251
5252 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5253 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005254 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5255 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005256 VOS_ASSERT(0);
5257 return -ENOMEM;
5258 }
5259 // WFD IE is saved to Additional IE ; it should be accumulated to handle
5260 // WPS IE + P2P IE + WFD IE
5261 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5262 pWextState->assocAddIE.length += eLen + 2;
5263
5264 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5265 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5266 }
5267#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005268 /* Appending HS 2.0 Indication Element in Assiciation Request */
5269 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005270 HS20_OUI_TYPE_SIZE)) )
5271 {
5272 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5273 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
5274 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005275
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005276 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5277 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005278 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5279 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005280 VOS_ASSERT(0);
5281 return -ENOMEM;
5282 }
5283 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5284 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005285
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005286 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5287 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5288 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005289
Jeff Johnson295189b2012-06-20 16:38:30 -07005290 break;
5291 case DOT11F_EID_RSN:
5292 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
5293 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5294 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
5295 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
5296 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
5297 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005298 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
5299 case DOT11F_EID_EXTCAP:
5300 {
5301 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5302 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
5303 __func__, eLen + 2);
5304
5305 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5306 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005307 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5308 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005309 VOS_ASSERT(0);
5310 return -ENOMEM;
5311 }
5312 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5313 pWextState->assocAddIE.length += eLen + 2;
5314
5315 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5316 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5317 break;
5318 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005319#ifdef FEATURE_WLAN_WAPI
5320 case WLAN_EID_WAPI:
5321 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
5322 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
5323 pAdapter->wapi_info.nWapiMode);
5324 tmp = (u16 *)ie;
5325 tmp = tmp + 2; // Skip element Id and Len, Version
5326 akmsuiteCount = WPA_GET_LE16(tmp);
5327 tmp = tmp + 1;
5328 akmlist = (int *)(tmp);
5329 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
5330 {
5331 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
5332 }
5333 else
5334 {
5335 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
5336 VOS_ASSERT(0);
5337 return -EINVAL;
5338 }
5339
5340 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
5341 {
5342 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005343 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005344 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
5345 }
5346 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
5347 {
5348 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005349 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005350 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
5351 }
5352 break;
5353#endif
5354 default:
5355 hddLog (VOS_TRACE_LEVEL_ERROR,
5356 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005357 /* when Unknown IE is received we should break and continue
5358 * to the next IE in the buffer instead we were returning
5359 * so changing this to break */
5360 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005361 }
5362 genie += eLen;
5363 remLen -= eLen;
5364 }
5365 EXIT();
5366 return 0;
5367}
5368
5369/*
5370 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5371 * This function is used to initialize the security
5372 * parameters during connect operation.
5373 */
5374int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
5375 struct cfg80211_connect_params *req
5376 )
5377{
5378 int status = 0;
5379 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5380 ENTER();
5381
5382 /*set wpa version*/
5383 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5384
5385 if (req->crypto.wpa_versions)
5386 {
5387 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
5388 && ( (req->ie_len)
5389 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
5390 // Make sure that it is including a WPA IE.
5391 /* Currently NL is putting WPA version 1 even for open,
5392 * since p2p ie is also put in same buffer.
5393 * */
5394 {
5395 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5396 }
5397 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
5398 {
5399 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5400 }
5401 }
5402
5403 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
5404 pWextState->wpaVersion);
5405
5406 /*set authentication type*/
5407 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
5408
5409 if (0 > status)
5410 {
5411 hddLog(VOS_TRACE_LEVEL_ERROR,
5412 "%s: failed to set authentication type ", __func__);
5413 return status;
5414 }
5415
5416 /*set key mgmt type*/
5417 if (req->crypto.n_akm_suites)
5418 {
5419 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
5420 if (0 > status)
5421 {
5422 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
5423 __func__);
5424 return status;
5425 }
5426 }
5427
5428 /*set pairwise cipher type*/
5429 if (req->crypto.n_ciphers_pairwise)
5430 {
5431 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
5432 req->crypto.ciphers_pairwise[0], true);
5433 if (0 > status)
5434 {
5435 hddLog(VOS_TRACE_LEVEL_ERROR,
5436 "%s: failed to set unicast cipher type", __func__);
5437 return status;
5438 }
5439 }
5440 else
5441 {
5442 /*Reset previous cipher suite to none*/
5443 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
5444 if (0 > status)
5445 {
5446 hddLog(VOS_TRACE_LEVEL_ERROR,
5447 "%s: failed to set unicast cipher type", __func__);
5448 return status;
5449 }
5450 }
5451
5452 /*set group cipher type*/
5453 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
5454 false);
5455
5456 if (0 > status)
5457 {
5458 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
5459 __func__);
5460 return status;
5461 }
5462
Chet Lanctot186b5732013-03-18 10:26:30 -07005463#ifdef WLAN_FEATURE_11W
5464 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
5465#endif
5466
Jeff Johnson295189b2012-06-20 16:38:30 -07005467 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
5468 if (req->ie_len)
5469 {
5470 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
5471 if ( 0 > status)
5472 {
5473 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
5474 __func__);
5475 return status;
5476 }
5477 }
5478
5479 /*incase of WEP set default key information*/
5480 if (req->key && req->key_len)
5481 {
5482 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
5483 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
5484 )
5485 {
5486 if ( IW_AUTH_KEY_MGMT_802_1X
5487 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
5488 {
5489 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
5490 __func__);
5491 return -EOPNOTSUPP;
5492 }
5493 else
5494 {
5495 u8 key_len = req->key_len;
5496 u8 key_idx = req->key_idx;
5497
5498 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
5499 && (CSR_MAX_NUM_KEY > key_idx)
5500 )
5501 {
5502 hddLog(VOS_TRACE_LEVEL_INFO,
5503 "%s: setting default wep key, key_idx = %hu key_len %hu",
5504 __func__, key_idx, key_len);
5505 vos_mem_copy(
5506 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
5507 req->key, key_len);
5508 pWextState->roamProfile.Keys.KeyLength[key_idx] =
5509 (u8)key_len;
5510 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
5511 }
5512 }
5513 }
5514 }
5515
5516 return status;
5517}
5518
5519/*
5520 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5521 * This function is used to initialize the security
5522 * parameters during connect operation.
5523 */
5524static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
5525 struct net_device *ndev,
5526 struct cfg80211_connect_params *req
5527 )
5528{
5529 int status = 0;
5530 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
5531 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
5532 hdd_context_t *pHddCtx = NULL;
5533
5534 ENTER();
5535
5536 hddLog(VOS_TRACE_LEVEL_INFO,
5537 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5538
5539 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5540 {
5541 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5542 "%s:LOGP in Progress. Ignore!!!", __func__);
5543 return -EAGAIN;
5544 }
5545
5546#ifdef WLAN_BTAMP_FEATURE
5547 //Infra connect not supported when AMP traffic is on.
5548 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
5549 {
5550 hddLog(VOS_TRACE_LEVEL_ERROR,
5551 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005552 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07005553 }
5554#endif
5555 /*initialise security parameters*/
5556 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
5557
5558 if ( 0 > status)
5559 {
5560 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
5561 __func__);
5562 return status;
5563 }
5564
5565 //If Device Mode is Station Concurrent Sessions Exit BMps
Jeff Johnsona8a1a482012-12-12 16:49:33 -08005566 //P2P Mode will be taken care in Open/close adapter
Jeff Johnson295189b2012-06-20 16:38:30 -07005567 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
5568 (vos_concurrent_sessions_running()))
5569 {
5570 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5571
5572 if (NULL != pVosContext)
5573 {
5574 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5575 if(NULL != pHddCtx)
5576 {
5577 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
5578 }
5579 }
5580 }
5581
Mohit Khanna765234a2012-09-11 15:08:35 -07005582 if ( req->channel )
5583 {
5584 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5585 req->ssid_len, req->bssid,
5586 req->channel->hw_value);
5587 }
5588 else
5589 {
5590 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5591 req->ssid_len, req->bssid,
5592 0);
5593 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005594
5595 if (0 > status)
5596 {
5597 //ReEnable BMPS if disabled
5598 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5599 (NULL != pHddCtx))
5600 {
5601 //ReEnable Bmps and Imps back
5602 hdd_enable_bmps_imps(pHddCtx);
5603 }
5604
5605 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5606 return status;
5607 }
5608 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
5609 EXIT();
5610 return status;
5611}
5612
5613
5614/*
5615 * FUNCTION: wlan_hdd_cfg80211_disconnect
5616 * This function is used to issue a disconnect request to SME
5617 */
5618static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
5619 struct net_device *dev,
5620 u16 reason
5621 )
5622{
5623 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5624 tCsrRoamProfile *pRoamProfile =
5625 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
5626 int status = 0;
5627 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005628#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005629 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005630 tANI_U8 staIdx;
5631#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005632
5633 ENTER();
5634
5635 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
5636 __func__,pAdapter->device_mode);
5637
5638 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5639 __func__, reason);
5640
5641 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
5642 {
5643 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5644 "%s:LOGP in Progress. Ignore!!!",__func__);
5645 return -EAGAIN;
5646 }
5647 if (NULL != pRoamProfile)
5648 {
5649 /*issue disconnect request to SME, if station is in connected state*/
5650 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
5651 {
5652 eCsrRoamDisconnectReason reasonCode =
5653 eCSR_DISCONNECT_REASON_UNSPECIFIED;
5654 switch(reason)
5655 {
5656 case WLAN_REASON_MIC_FAILURE:
5657 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
5658 break;
5659
5660 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
5661 case WLAN_REASON_DISASSOC_AP_BUSY:
5662 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
5663 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
5664 break;
5665
5666 case WLAN_REASON_PREV_AUTH_NOT_VALID:
5667 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
5668 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
5669 break;
5670
5671 case WLAN_REASON_DEAUTH_LEAVING:
5672 default:
5673 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
5674 break;
5675 }
5676 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5677 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
5678 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5679
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005680#ifdef FEATURE_WLAN_TDLS
5681 /* First clean up the tdls peers if any */
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005682 for (staIdx = 0 ; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005683 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005684 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId == pAdapter->sessionId) &&
5685 (pHddCtx->tdlsConnInfo[staIdx].staId))
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005686 {
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005687 uint8 *mac;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005688 mac = pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005689 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07005690 "%s: call sme_DeleteTdlsPeerSta staId %d sessionId %d " MAC_ADDRESS_STR,
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005691 __func__, pHddCtx->tdlsConnInfo[staIdx].staId, pAdapter->sessionId,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07005692 MAC_ADDR_ARRAY(mac));
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005693 sme_DeleteTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005694 pAdapter->sessionId,
5695 mac);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005696 }
5697 }
5698#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005699 /*issue disconnect*/
5700 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5701 pAdapter->sessionId, reasonCode);
5702
5703 if ( 0 != status)
5704 {
5705 hddLog(VOS_TRACE_LEVEL_ERROR,
5706 "%s csrRoamDisconnect failure, returned %d \n",
5707 __func__, (int)status );
5708 return -EINVAL;
5709 }
5710
5711 wait_for_completion_interruptible_timeout(
5712 &pAdapter->disconnect_comp_var,
5713 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5714
5715
5716 /*stop tx queues*/
5717 netif_tx_disable(dev);
5718 netif_carrier_off(dev);
5719 }
5720 }
5721 else
5722 {
5723 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
5724 }
5725
5726 return status;
5727}
5728
5729/*
5730 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
5731 * This function is used to initialize the security
5732 * settings in IBSS mode.
5733 */
5734static int wlan_hdd_cfg80211_set_privacy_ibss(
5735 hdd_adapter_t *pAdapter,
5736 struct cfg80211_ibss_params *params
5737 )
5738{
5739 int status = 0;
5740 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5741 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5742 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5743
5744 ENTER();
5745
5746 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5747
5748 if (params->ie_len && ( NULL != params->ie) )
5749 {
5750 if (WLAN_EID_RSN == params->ie[0])
5751 {
5752 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5753 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5754 }
5755 else
5756 {
5757 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5758 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5759 }
5760 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
5761
5762 if (0 > status)
5763 {
5764 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
5765 __func__);
5766 return status;
5767 }
5768 }
5769
5770 pWextState->roamProfile.AuthType.authType[0] =
5771 pHddStaCtx->conn_info.authType =
5772 eCSR_AUTH_TYPE_OPEN_SYSTEM;
5773
5774 if (params->privacy)
5775 {
5776 /* Security enabled IBSS, At this time there is no information available
5777 * about the security paramters, so initialise the encryption type to
5778 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
5779 * The correct security parameters will be updated later in
5780 * wlan_hdd_cfg80211_add_key */
5781 /* Hal expects encryption type to be set inorder
5782 *enable privacy bit in beacons */
5783
5784 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5785 }
5786
5787 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5788 pWextState->roamProfile.EncryptionType.numEntries = 1;
5789 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
5790
5791 return status;
5792}
5793
5794/*
5795 * FUNCTION: wlan_hdd_cfg80211_join_ibss
5796 * This function is used to create/join an IBSS
5797 */
5798static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
5799 struct net_device *dev,
5800 struct cfg80211_ibss_params *params
5801 )
5802{
5803 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5804 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5805 tCsrRoamProfile *pRoamProfile;
5806 int status;
5807 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5808
5809 ENTER();
5810
5811 hddLog(VOS_TRACE_LEVEL_INFO,
5812 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5813
5814 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5815 {
5816 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5817 "%s:LOGP in Progress. Ignore!!!", __func__);
5818 return -EAGAIN;
5819 }
5820
5821 if (NULL == pWextState)
5822 {
5823 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5824 __func__);
5825 return -EIO;
5826 }
5827
5828 pRoamProfile = &pWextState->roamProfile;
5829
5830 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
5831 {
5832 hddLog (VOS_TRACE_LEVEL_ERROR,
5833 "%s Interface type is not set to IBSS \n", __func__);
5834 return -EINVAL;
5835 }
5836
5837 /* Set Channel */
5838 if (NULL != params->channel)
5839 {
5840 u8 channelNum;
5841 if (IEEE80211_BAND_5GHZ == params->channel->band)
5842 {
5843 hddLog(VOS_TRACE_LEVEL_ERROR,
5844 "%s: IBSS join is called with unsupported band %d",
5845 __func__, params->channel->band);
5846 return -EOPNOTSUPP;
5847 }
5848
5849 /* Get channel number */
5850 channelNum =
5851 ieee80211_frequency_to_channel(params->channel->center_freq);
5852
5853 /*TODO: use macro*/
5854 if (14 >= channelNum)
5855 {
5856 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5857 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5858 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5859 int indx;
5860
5861 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5862 validChan, &numChans))
5863 {
5864 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
5865 __func__);
5866 return -EOPNOTSUPP;
5867 }
5868
5869 for (indx = 0; indx < numChans; indx++)
5870 {
5871 if (channelNum == validChan[indx])
5872 {
5873 break;
5874 }
5875 }
5876 if (indx >= numChans)
5877 {
5878 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
5879 __func__, channelNum);
5880 return -EINVAL;
5881 }
5882 /* Set the Operational Channel */
5883 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
5884 channelNum);
5885 pRoamProfile->ChannelInfo.numOfChannels = 1;
5886 pHddStaCtx->conn_info.operationChannel = channelNum;
5887 pRoamProfile->ChannelInfo.ChannelList =
5888 &pHddStaCtx->conn_info.operationChannel;
5889 }
5890 else
5891 {
5892 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5893 __func__, channelNum);
5894 return -EINVAL;
5895 }
5896 }
5897
5898 /* Initialize security parameters */
5899 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5900 if (status < 0)
5901 {
5902 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5903 __func__);
5904 return status;
5905 }
5906
5907 /* Issue connect start */
5908 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005909 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005910
5911 if (0 > status)
5912 {
5913 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5914 return status;
5915 }
5916
5917 return 0;
5918}
5919
5920/*
5921 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5922 * This function is used to leave an IBSS
5923 */
5924static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5925 struct net_device *dev
5926 )
5927{
5928 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5929 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5930 tCsrRoamProfile *pRoamProfile;
5931
5932 ENTER();
5933
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005934 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5935 {
5936 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5937 "%s:LOGP in Progress. Ignore!!!", __func__);
5938 return -EAGAIN;
5939 }
5940
Jeff Johnson295189b2012-06-20 16:38:30 -07005941 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5942 if (NULL == pWextState)
5943 {
5944 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5945 __func__);
5946 return -EIO;
5947 }
5948
5949 pRoamProfile = &pWextState->roamProfile;
5950
5951 /* Issue disconnect only if interface type is set to IBSS */
5952 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5953 {
5954 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5955 __func__);
5956 return -EINVAL;
5957 }
5958
5959 /* Issue Disconnect request */
5960 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5961 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5962 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5963
5964 return 0;
5965}
5966
5967/*
5968 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5969 * This function is used to set the phy parameters
5970 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5971 */
5972static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5973 u32 changed)
5974{
5975 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5976 tHalHandle hHal = pHddCtx->hHal;
5977
5978 ENTER();
5979
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005980 if ( pHddCtx->isLogpInProgress )
5981 {
5982 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5983 "%s:LOGP in Progress. Ignore!!!", __func__);
5984 return -EAGAIN;
5985 }
5986
Jeff Johnson295189b2012-06-20 16:38:30 -07005987 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
5988 {
5989 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
5990 WNI_CFG_RTS_THRESHOLD_STAMAX :
5991 wiphy->rts_threshold;
5992
5993 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
5994 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
5995 {
5996 hddLog(VOS_TRACE_LEVEL_ERROR,
5997 "%s: Invalid RTS Threshold value %hu",
5998 __func__, rts_threshold);
5999 return -EINVAL;
6000 }
6001
6002 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
6003 rts_threshold, ccmCfgSetCallback,
6004 eANI_BOOLEAN_TRUE))
6005 {
6006 hddLog(VOS_TRACE_LEVEL_ERROR,
6007 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
6008 __func__, rts_threshold);
6009 return -EIO;
6010 }
6011
6012 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
6013 rts_threshold);
6014 }
6015
6016 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
6017 {
6018 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
6019 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
6020 wiphy->frag_threshold;
6021
6022 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
6023 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
6024 {
6025 hddLog(VOS_TRACE_LEVEL_ERROR,
6026 "%s: Invalid frag_threshold value %hu", __func__,
6027 frag_threshold);
6028 return -EINVAL;
6029 }
6030
6031 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
6032 frag_threshold, ccmCfgSetCallback,
6033 eANI_BOOLEAN_TRUE))
6034 {
6035 hddLog(VOS_TRACE_LEVEL_ERROR,
6036 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
6037 __func__, frag_threshold);
6038 return -EIO;
6039 }
6040
6041 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
6042 frag_threshold);
6043 }
6044
6045 if ((changed & WIPHY_PARAM_RETRY_SHORT)
6046 || (changed & WIPHY_PARAM_RETRY_LONG))
6047 {
6048 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
6049 wiphy->retry_short :
6050 wiphy->retry_long;
6051
6052 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
6053 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
6054 {
6055 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
6056 __func__, retry_value);
6057 return -EINVAL;
6058 }
6059
6060 if (changed & WIPHY_PARAM_RETRY_SHORT)
6061 {
6062 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
6063 retry_value, ccmCfgSetCallback,
6064 eANI_BOOLEAN_TRUE))
6065 {
6066 hddLog(VOS_TRACE_LEVEL_ERROR,
6067 "%s: ccmCfgSetInt failed for long retry count %hu",
6068 __func__, retry_value);
6069 return -EIO;
6070 }
6071 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
6072 __func__, retry_value);
6073 }
6074 else if (changed & WIPHY_PARAM_RETRY_SHORT)
6075 {
6076 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
6077 retry_value, ccmCfgSetCallback,
6078 eANI_BOOLEAN_TRUE))
6079 {
6080 hddLog(VOS_TRACE_LEVEL_ERROR,
6081 "%s: ccmCfgSetInt failed for short retry count %hu",
6082 __func__, retry_value);
6083 return -EIO;
6084 }
6085 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
6086 __func__, retry_value);
6087 }
6088 }
6089
6090 return 0;
6091}
6092
6093/*
6094 * FUNCTION: wlan_hdd_cfg80211_set_txpower
6095 * This function is used to set the txpower
6096 */
6097static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
6098#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
6099 enum tx_power_setting type,
6100#else
6101 enum nl80211_tx_power_setting type,
6102#endif
6103 int dbm)
6104{
6105 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6106 tHalHandle hHal = pHddCtx->hHal;
6107 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
6108 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
6109
6110 ENTER();
6111
6112 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
6113 dbm, ccmCfgSetCallback,
6114 eANI_BOOLEAN_TRUE))
6115 {
6116 hddLog(VOS_TRACE_LEVEL_ERROR,
6117 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
6118 return -EIO;
6119 }
6120
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006121 if ( pHddCtx->isLogpInProgress )
6122 {
6123 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6124 "%s:LOGP in Progress. Ignore!!!", __func__);
6125 return -EAGAIN;
6126 }
6127
Jeff Johnson295189b2012-06-20 16:38:30 -07006128 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
6129 dbm);
6130
6131 switch(type)
6132 {
6133 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
6134 /* Fall through */
6135 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
6136 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
6137 {
6138 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
6139 __func__);
6140 return -EIO;
6141 }
6142 break;
6143 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
6144 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
6145 __func__);
6146 return -EOPNOTSUPP;
6147 break;
6148 default:
6149 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
6150 __func__, type);
6151 return -EIO;
6152 }
6153
6154 return 0;
6155}
6156
6157/*
6158 * FUNCTION: wlan_hdd_cfg80211_get_txpower
6159 * This function is used to read the txpower
6160 */
6161static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
6162{
6163
6164 hdd_adapter_t *pAdapter;
6165 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6166
Jeff Johnsone7245742012-09-05 17:12:55 -07006167 ENTER();
6168
Jeff Johnson295189b2012-06-20 16:38:30 -07006169 if (NULL == pHddCtx)
6170 {
6171 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
6172 *dbm = 0;
6173 return -ENOENT;
6174 }
6175
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006176 if ( pHddCtx->isLogpInProgress )
6177 {
6178 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6179 "%s:LOGP in Progress. Ignore!!!", __func__);
6180 return -EAGAIN;
6181 }
6182
Jeff Johnson295189b2012-06-20 16:38:30 -07006183 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
6184 if (NULL == pAdapter)
6185 {
6186 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
6187 return -ENOENT;
6188 }
6189
6190 wlan_hdd_get_classAstats(pAdapter);
6191 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
6192
Jeff Johnsone7245742012-09-05 17:12:55 -07006193 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006194 return 0;
6195}
6196
6197static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
6198 u8* mac, struct station_info *sinfo)
6199{
6200 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
6201 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6202 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
6203 tANI_U8 rate_flags;
6204
6205 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6206 hdd_config_t *pCfg = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07006207
6208 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
6209 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
6210 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
6211 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
6212 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
6213 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
6214 tANI_U16 maxRate = 0;
6215 tANI_U16 myRate;
6216 tANI_U16 currentRate = 0;
6217 tANI_U8 maxSpeedMCS = 0;
6218 tANI_U8 maxMCSIdx = 0;
6219 tANI_U8 rateFlag = 1;
6220 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006221 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07006222
Leo Chang6f8870f2013-03-26 18:11:36 -07006223#ifdef WLAN_FEATURE_11AC
6224 tANI_U32 vht_mcs_map;
6225 eDataRate11ACMaxMcs vhtMaxMcs;
6226#endif /* WLAN_FEATURE_11AC */
6227
Jeff Johnsone7245742012-09-05 17:12:55 -07006228 ENTER();
6229
Jeff Johnson295189b2012-06-20 16:38:30 -07006230 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
6231 (0 == ssidlen))
6232 {
6233 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
6234 " Invalid ssidlen, %d", __func__, ssidlen);
6235 /*To keep GUI happy*/
6236 return 0;
6237 }
6238
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006239 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6240 {
6241 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6242 "%s:LOGP in Progress. Ignore!!!", __func__);
6243 return -EAGAIN;
6244 }
6245
Jeff Johnson295189b2012-06-20 16:38:30 -07006246 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
6247 sinfo->filled |= STATION_INFO_SIGNAL;
6248
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006249 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006250 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
6251
6252 //convert to the UI units of 100kbps
6253 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
6254
6255#ifdef LINKSPEED_DEBUG_ENABLED
Leo Chang6f8870f2013-03-26 18:11:36 -07006256 pr_info("RSSI %d, RLMS %u, rate %d, rssi high %d, rssi mid %d, rssi low %d, rate_flags 0x%x, MCS %d\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07006257 sinfo->signal,
6258 pCfg->reportMaxLinkSpeed,
6259 myRate,
6260 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006261 (int) pCfg->linkSpeedRssiMid,
6262 (int) pCfg->linkSpeedRssiLow,
Leo Chang6f8870f2013-03-26 18:11:36 -07006263 (int) rate_flags,
6264 (int) pAdapter->hdd_stats.ClassA_stat.mcs_index);
Jeff Johnson295189b2012-06-20 16:38:30 -07006265#endif //LINKSPEED_DEBUG_ENABLED
6266
6267 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
6268 {
6269 // we do not want to necessarily report the current speed
6270 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
6271 {
6272 // report the max possible speed
6273 rssidx = 0;
6274 }
6275 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
6276 {
6277 // report the max possible speed with RSSI scaling
6278 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
6279 {
6280 // report the max possible speed
6281 rssidx = 0;
6282 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006283 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07006284 {
6285 // report middle speed
6286 rssidx = 1;
6287 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006288 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
6289 {
6290 // report middle speed
6291 rssidx = 2;
6292 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006293 else
6294 {
6295 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006296 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07006297 }
6298 }
6299 else
6300 {
6301 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
6302 hddLog(VOS_TRACE_LEVEL_ERROR,
6303 "%s: Invalid value for reportMaxLinkSpeed: %u",
6304 __func__, pCfg->reportMaxLinkSpeed);
6305 rssidx = 0;
6306 }
6307
6308 maxRate = 0;
6309
6310 /* Get Basic Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306311 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_OPERATIONAL_RATE_SET,
6312 OperationalRates, &ORLeng))
6313 {
6314 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6315 /*To keep GUI happy*/
6316 return 0;
6317 }
6318
Jeff Johnson295189b2012-06-20 16:38:30 -07006319 for (i = 0; i < ORLeng; i++)
6320 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006321 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006322 {
6323 /* Validate Rate Set */
6324 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
6325 {
6326 currentRate = supported_data_rate[j].supported_rate[rssidx];
6327 break;
6328 }
6329 }
6330 /* Update MAX rate */
6331 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6332 }
6333
6334 /* Get Extended Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306335 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
6336 ExtendedRates, &ERLeng))
6337 {
6338 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6339 /*To keep GUI happy*/
6340 return 0;
6341 }
6342
Jeff Johnson295189b2012-06-20 16:38:30 -07006343 for (i = 0; i < ERLeng; i++)
6344 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006345 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006346 {
6347 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
6348 {
6349 currentRate = supported_data_rate[j].supported_rate[rssidx];
6350 break;
6351 }
6352 }
6353 /* Update MAX rate */
6354 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6355 }
6356
6357 /* Get MCS Rate Set -- but only if we are connected at MCS
6358 rates or if we are always reporting max speed or if we have
6359 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006360 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07006361 {
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306362 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_CURRENT_MCS_SET,
6363 MCSRates, &MCSLeng))
6364 {
6365 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6366 /*To keep GUI happy*/
6367 return 0;
6368 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006369 rateFlag = 0;
Leo Chang6f8870f2013-03-26 18:11:36 -07006370#ifdef WLAN_FEATURE_11AC
6371 /* VHT80 rate has seperate rate table */
6372 if (rate_flags & eHAL_TX_RATE_VHT80)
Jeff Johnson295189b2012-06-20 16:38:30 -07006373 {
Leo Chang6f8870f2013-03-26 18:11:36 -07006374 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_rate[rateFlag];
6375 ccmCfgGetInt(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_VHT_TX_MCS_MAP, &vht_mcs_map);
6376 if (rate_flags & eHAL_TX_RATE_SGI)
Jeff Johnson295189b2012-06-20 16:38:30 -07006377 {
Leo Chang6f8870f2013-03-26 18:11:36 -07006378 rateFlag |= 1;
Jeff Johnson295189b2012-06-20 16:38:30 -07006379 }
Leo Chang6f8870f2013-03-26 18:11:36 -07006380 vhtMaxMcs = (eDataRate11ACMaxMcs)(vht_mcs_map & DATA_RATE_11AC_MCS_MASK);
6381 if (DATA_RATE_11AC_MAX_MCS_7 == vhtMaxMcs)
Jeff Johnson295189b2012-06-20 16:38:30 -07006382 {
Leo Chang6f8870f2013-03-26 18:11:36 -07006383 maxMCSIdx = 7;
6384 }
6385 else if (DATA_RATE_11AC_MAX_MCS_8 == vhtMaxMcs)
6386 {
6387 maxMCSIdx = 8;
6388 }
6389 else if (DATA_RATE_11AC_MAX_MCS_9 == vhtMaxMcs)
6390 {
6391 maxMCSIdx = 9;
6392 }
6393 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_rate[rateFlag];
6394 maxSpeedMCS = 1;
6395 if (currentRate > maxRate)
6396 {
6397 maxRate = currentRate;
6398 }
6399 }
6400 else
6401#endif /* WLAN_FEATURE_11AC */
6402 {
6403 if (rate_flags & eHAL_TX_RATE_HT40)
6404 {
6405 rateFlag |= 1;
6406 }
6407 if (rate_flags & eHAL_TX_RATE_SGI)
6408 {
6409 rateFlag |= 2;
6410 }
6411
6412 for (i = 0; i < MCSLeng; i++)
6413 {
6414 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
6415 for (j = 0; j < temp; j++)
6416 {
6417 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
6418 {
6419 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
6420 break;
6421 }
6422 }
6423 if ((j < temp) && (currentRate > maxRate))
6424 {
6425 maxRate = currentRate;
6426 maxSpeedMCS = 1;
6427 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
6428 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006429 }
6430 }
6431 }
6432
6433 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006434 if (((maxRate < myRate) && (0 == rssidx)) ||
6435 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006436 {
6437 maxRate = myRate;
6438 if (rate_flags & eHAL_TX_RATE_LEGACY)
6439 {
6440 maxSpeedMCS = 0;
6441 }
6442 else
6443 {
6444 maxSpeedMCS = 1;
6445 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6446 }
6447 }
6448
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006449 if ((!maxSpeedMCS) || (0 != rssidx))
Jeff Johnson295189b2012-06-20 16:38:30 -07006450 {
6451 sinfo->txrate.legacy = maxRate;
6452#ifdef LINKSPEED_DEBUG_ENABLED
6453 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
6454#endif //LINKSPEED_DEBUG_ENABLED
6455 }
6456 else
6457 {
6458 sinfo->txrate.mcs = maxMCSIdx;
Leo Chang6f8870f2013-03-26 18:11:36 -07006459#ifdef WLAN_FEATURE_11AC
6460 sinfo->txrate.nss = 1;
6461 if (rate_flags & eHAL_TX_RATE_VHT80)
6462 {
6463 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
6464 }
6465 else
6466#endif /* WLAN_FEATURE_11AC */
6467 {
6468 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6469 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006470 if (rate_flags & eHAL_TX_RATE_SGI)
6471 {
6472 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6473 }
6474 if (rate_flags & eHAL_TX_RATE_HT40)
6475 {
6476 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6477 }
Leo Chang6f8870f2013-03-26 18:11:36 -07006478#ifdef WLAN_FEATURE_11AC
6479 else if (rate_flags & eHAL_TX_RATE_VHT80)
6480 {
6481 sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
6482 }
6483#endif /* WLAN_FEATURE_11AC */
Jeff Johnson295189b2012-06-20 16:38:30 -07006484#ifdef LINKSPEED_DEBUG_ENABLED
6485 pr_info("Reporting MCS rate %d flags %x\n",
6486 sinfo->txrate.mcs,
6487 sinfo->txrate.flags );
6488#endif //LINKSPEED_DEBUG_ENABLED
6489 }
6490 }
6491 else
6492 {
6493 // report current rate instead of max rate
6494
6495 if (rate_flags & eHAL_TX_RATE_LEGACY)
6496 {
6497 //provide to the UI in units of 100kbps
6498 sinfo->txrate.legacy = myRate;
6499#ifdef LINKSPEED_DEBUG_ENABLED
6500 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
6501#endif //LINKSPEED_DEBUG_ENABLED
6502 }
6503 else
6504 {
6505 //must be MCS
6506 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
Leo Chang6f8870f2013-03-26 18:11:36 -07006507#ifdef WLAN_FEATURE_11AC
6508 sinfo->txrate.nss = 1;
6509 if (rate_flags & eHAL_TX_RATE_VHT80)
6510 {
6511 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
6512 }
6513 else
6514#endif /* WLAN_FEATURE_11AC */
6515 {
6516 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6517 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006518 if (rate_flags & eHAL_TX_RATE_SGI)
6519 {
6520 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6521 }
6522 if (rate_flags & eHAL_TX_RATE_HT40)
6523 {
6524 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6525 }
Leo Chang6f8870f2013-03-26 18:11:36 -07006526#ifdef WLAN_FEATURE_11AC
6527 else if (rate_flags & eHAL_TX_RATE_VHT80)
6528 {
6529 sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
6530 }
6531#endif /* WLAN_FEATURE_11AC */
Jeff Johnson295189b2012-06-20 16:38:30 -07006532#ifdef LINKSPEED_DEBUG_ENABLED
6533 pr_info("Reporting actual MCS rate %d flags %x\n",
6534 sinfo->txrate.mcs,
6535 sinfo->txrate.flags );
6536#endif //LINKSPEED_DEBUG_ENABLED
6537 }
6538 }
6539 sinfo->filled |= STATION_INFO_TX_BITRATE;
6540
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006541 sinfo->tx_packets =
6542 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
6543 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
6544 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
6545 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
6546
6547 sinfo->tx_retries =
6548 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
6549 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
6550 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
6551 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
6552
6553 sinfo->tx_failed =
6554 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
6555 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
6556 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
6557 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
6558
6559 sinfo->filled |=
6560 STATION_INFO_TX_PACKETS |
6561 STATION_INFO_TX_RETRIES |
6562 STATION_INFO_TX_FAILED;
6563
6564 EXIT();
6565 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006566}
6567
6568static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
6569 struct net_device *dev, bool mode, v_SINT_t timeout)
6570{
6571 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6572 VOS_STATUS vos_status;
6573
Jeff Johnsone7245742012-09-05 17:12:55 -07006574 ENTER();
6575
Jeff Johnson295189b2012-06-20 16:38:30 -07006576 if (NULL == pAdapter)
6577 {
6578 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6579 return -ENODEV;
6580 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006581 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6582 {
6583 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6584 "%s:LOGP in Progress. Ignore!!!", __func__);
6585 return -EAGAIN;
6586 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006587
6588 /**The get power cmd from the supplicant gets updated by the nl only
6589 *on successful execution of the function call
6590 *we are oppositely mapped w.r.t mode in the driver
6591 **/
6592 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
6593
Jeff Johnsone7245742012-09-05 17:12:55 -07006594 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006595 if (VOS_STATUS_E_FAILURE == vos_status)
6596 {
6597 return -EINVAL;
6598 }
6599 return 0;
6600}
6601
6602
6603#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6604static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
6605 struct net_device *netdev,
6606 u8 key_index)
6607{
Jeff Johnsone7245742012-09-05 17:12:55 -07006608 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006609 return 0;
6610}
6611#endif //LINUX_VERSION_CODE
6612
6613#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
6614static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6615 struct net_device *dev,
6616 struct ieee80211_txq_params *params)
6617{
Jeff Johnsone7245742012-09-05 17:12:55 -07006618 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006619 return 0;
6620}
6621#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6622static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6623 struct ieee80211_txq_params *params)
6624{
Jeff Johnsone7245742012-09-05 17:12:55 -07006625 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006626 return 0;
6627}
6628#endif //LINUX_VERSION_CODE
6629
6630static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
6631 struct net_device *dev, u8 *mac)
6632{
6633 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006634 VOS_STATUS vos_status;
6635 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006636
Jeff Johnsone7245742012-09-05 17:12:55 -07006637 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006638 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6639 {
6640 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6641 return -EINVAL;
6642 }
6643
6644 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6645 {
6646 hddLog( LOGE,
6647 "%s: Wlan Load/Unload is in progress", __func__);
6648 return -EBUSY;
6649 }
6650
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006651 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6652 {
6653 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6654 "%s:LOGP in Progress. Ignore!!!", __func__);
6655 return -EAGAIN;
6656 }
6657
Jeff Johnson295189b2012-06-20 16:38:30 -07006658 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006659 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006660 )
6661 {
6662 if( NULL == mac )
6663 {
6664 v_U16_t i;
6665 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
6666 {
6667 if(pAdapter->aStaInfo[i].isUsed)
6668 {
6669 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
6670 hddLog(VOS_TRACE_LEVEL_INFO,
6671 "%s: Delete STA with MAC::"
6672 "%02x:%02x:%02x:%02x:%02x:%02x",
6673 __func__,
6674 macAddr[0], macAddr[1], macAddr[2],
6675 macAddr[3], macAddr[4], macAddr[5]);
6676 hdd_softap_sta_deauth(pAdapter, macAddr);
6677 }
6678 }
6679 }
6680 else
6681 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006682
6683 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
6684 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6685 {
6686 hddLog(VOS_TRACE_LEVEL_INFO,
6687 "%s: Skip this DEL STA as this is not used::"
6688 "%02x:%02x:%02x:%02x:%02x:%02x",
6689 __func__,
6690 mac[0], mac[1], mac[2],
6691 mac[3], mac[4], mac[5]);
6692 return -ENOENT;
6693 }
6694
6695 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
6696 {
6697 hddLog(VOS_TRACE_LEVEL_INFO,
6698 "%s: Skip this DEL STA as deauth is in progress::"
6699 "%02x:%02x:%02x:%02x:%02x:%02x",
6700 __func__,
6701 mac[0], mac[1], mac[2],
6702 mac[3], mac[4], mac[5]);
6703 return -ENOENT;
6704 }
6705
6706 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
6707
Jeff Johnson295189b2012-06-20 16:38:30 -07006708 hddLog(VOS_TRACE_LEVEL_INFO,
6709 "%s: Delete STA with MAC::"
6710 "%02x:%02x:%02x:%02x:%02x:%02x",
6711 __func__,
6712 mac[0], mac[1], mac[2],
6713 mac[3], mac[4], mac[5]);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006714
6715 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
6716 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6717 {
6718 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
6719 hddLog(VOS_TRACE_LEVEL_INFO,
6720 "%s: STA removal failed for ::"
6721 "%02x:%02x:%02x:%02x:%02x:%02x",
6722 __func__,
6723 mac[0], mac[1], mac[2],
6724 mac[3], mac[4], mac[5]);
6725 return -ENOENT;
6726 }
6727
Jeff Johnson295189b2012-06-20 16:38:30 -07006728 }
6729 }
6730
6731 EXIT();
6732
6733 return 0;
6734}
6735
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006736static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
6737 struct net_device *dev, u8 *mac, struct station_parameters *params)
6738{
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006739 int status = -EPERM;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006740#ifdef FEATURE_WLAN_TDLS
6741 u32 mask, set;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006742 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006743 mask = params->sta_flags_mask;
6744
6745 set = params->sta_flags_set;
6746
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006747#ifdef WLAN_FEATURE_TDLS_DEBUG
6748 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6749 "%s: mask 0x%x set 0x%x " MAC_ADDRESS_STR,
6750 __func__, mask, set, MAC_ADDR_ARRAY(mac));
6751#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006752
6753 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6754 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006755 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006756 }
6757 }
6758#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006759 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006760}
6761
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006762
6763#ifdef FEATURE_WLAN_LFR
6764static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006765 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006766{
6767#define MAX_PMKSAIDS_IN_CACHE 8
6768 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -07006769 static tANI_U32 i; // HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006770 tANI_U32 j=0;
6771 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6772 tHalHandle halHandle;
6773 eHalStatus result;
6774 tANI_U8 BSSIDMatched = 0;
6775
Jeff Johnsone7245742012-09-05 17:12:55 -07006776 ENTER();
6777
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006778 // Validate pAdapter
6779 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6780 {
6781 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6782 return -EINVAL;
6783 }
6784
6785 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6786 {
6787 hddLog( LOGE,
6788 "%s: Wlan Load/Unload is in progress", __func__);
6789 return -EBUSY;
6790 }
6791
6792 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6793 {
6794 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6795 "%s:LOGP in Progress. Ignore!!!", __func__);
6796 return -EAGAIN;
6797 }
6798
6799 // Retrieve halHandle
6800 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
6801
6802 for (j = 0; j < i; j++)
6803 {
6804 if(vos_mem_compare(PMKIDCache[j].BSSID,
6805 pmksa->bssid, WNI_CFG_BSSID_LEN))
6806 {
6807 /* BSSID matched previous entry. Overwrite it. */
6808 BSSIDMatched = 1;
6809 vos_mem_copy(PMKIDCache[j].BSSID,
6810 pmksa->bssid, WNI_CFG_BSSID_LEN);
6811 vos_mem_copy(PMKIDCache[j].PMKID,
6812 pmksa->pmkid,
6813 CSR_RSN_PMKID_SIZE);
6814 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006815 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006816 dump_bssid(pmksa->bssid);
6817 dump_pmkid(halHandle, pmksa->pmkid);
6818 break;
6819 }
6820 }
6821
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07006822 /* Check we compared all entries,if then take the first slot now */
6823 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
6824
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006825 if (!BSSIDMatched)
6826 {
6827 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
6828 vos_mem_copy(PMKIDCache[i].BSSID,
6829 pmksa->bssid, ETHER_ADDR_LEN);
6830 vos_mem_copy(PMKIDCache[i].PMKID,
6831 pmksa->pmkid,
6832 CSR_RSN_PMKID_SIZE);
6833 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006834 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006835 dump_bssid(pmksa->bssid);
6836 dump_pmkid(halHandle, pmksa->pmkid);
6837 // Increment the HDD Local Cache index
6838 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
6839 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
6840 }
6841
6842
6843 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
6844 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006845 // __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006846 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006847 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006848 // Finally set the PMKSA ID Cache in CSR
6849 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
6850 PMKIDCache,
6851 i );
6852 return 0;
6853}
6854
6855
6856static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006857 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006858{
Jeff Johnsone7245742012-09-05 17:12:55 -07006859 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006860 // TODO: Implement this later.
6861 return 0;
6862}
6863
6864static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
6865{
Jeff Johnsone7245742012-09-05 17:12:55 -07006866 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006867 // TODO: Implement this later.
6868 return 0;
6869}
6870#endif
6871
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006872#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6873static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
6874 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
6875{
6876 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6877 hdd_station_ctx_t *pHddStaCtx;
6878
6879 if (NULL == pAdapter)
6880 {
6881 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6882 return -ENODEV;
6883 }
6884
6885 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6886
6887 // Added for debug on reception of Re-assoc Req.
6888 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6889 {
6890 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
6891 ftie->ie_len);
6892 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
6893 }
6894
6895#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
6896 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
6897 ftie->ie_len);
6898#endif
6899
6900 // Pass the received FT IEs to SME
Gopichand Nakkala356fb102013-03-06 12:34:04 +05306901 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6902 (const u8 *)ftie->ie,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006903 ftie->ie_len);
6904 return 0;
6905}
6906#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006907
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006908#ifdef FEATURE_WLAN_TDLS
6909static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
6910 u8 *peer, u8 action_code, u8 dialog_token,
6911 u16 status_code, const u8 *buf, size_t len)
6912{
6913
6914 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6915 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006916 u8 peerMac[6];
6917 VOS_STATUS status;
Gopichand Nakkala05922802013-03-14 12:23:19 -07006918 int max_sta_failed = 0;
Hoonki Leea34dd892013-02-05 22:56:02 -08006919 int responder;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006920
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006921 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006922 {
6923 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6924 "Invalid arguments");
6925 return -EINVAL;
6926 }
6927
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006928 if (pHddCtx->isLogpInProgress)
6929 {
6930 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6931 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006932 wlan_hdd_tdls_set_link_status(pAdapter, peer, eTDLS_LINK_IDLE);
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006933 return -EBUSY;
6934 }
6935
Hoonki Lee27511902013-03-14 18:19:06 -07006936 if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006937 {
Hoonki Lee27511902013-03-14 18:19:06 -07006938 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6939 "%s: TDLS mode is disabled OR not enabled in FW."
6940 MAC_ADDRESS_STR " action %d declined.",
6941 __func__, MAC_ADDR_ARRAY(peer), action_code);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006942 return -ENOTSUPP;
6943 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006944
Hoonki Lee27511902013-03-14 18:19:06 -07006945 if ((SIR_MAC_TDLS_SETUP_RSP == action_code) ||
6946 (SIR_MAC_TDLS_DIS_RSP == action_code))
6947 {
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07006948 wlan_hdd_tdls_set_cap (pAdapter, peer, eTDLS_CAP_SUPPORTED);
Hoonki Lee27511902013-03-14 18:19:06 -07006949 }
6950
6951 /* other than teardown frame, other mgmt frames are not sent if disabled */
6952 if (SIR_MAC_TDLS_TEARDOWN != action_code)
6953 {
6954 /* if tdls_mode is disabled to respond to peer's request */
6955 if (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode)
6956 {
6957 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6958 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006959 " TDLS mode is disabled. action %d declined.",
6960 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee27511902013-03-14 18:19:06 -07006961
6962 return -ENOTSUPP;
6963 }
6964 }
6965
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006966 if (WLAN_IS_TDLS_SETUP_ACTION(action_code))
6967 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006968 if (wlan_hdd_tdls_is_progress(pAdapter, peer, TRUE))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006969 {
6970 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006971 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006972 " TDLS setup is ongoing. action %d declined.",
6973 __func__, MAC_ADDR_ARRAY(peer), action_code);
6974 return -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006975 }
6976 }
6977
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006978 if (SIR_MAC_TDLS_SETUP_REQ == action_code ||
6979 SIR_MAC_TDLS_SETUP_RSP == action_code )
Lee Hoonkic1262f22013-01-24 21:59:00 -08006980 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006981 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
Lee Hoonkic1262f22013-01-24 21:59:00 -08006982 {
6983 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
6984 we return error code at 'add_station()'. Hence we have this
6985 check again in addtion to add_station().
6986 Anyway, there is no hard to double-check. */
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006987 if (SIR_MAC_TDLS_SETUP_REQ == action_code)
Lee Hoonkic1262f22013-01-24 21:59:00 -08006988 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006989 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6990 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006991 " TDLS Max peer already connected. action %d declined.",
6992 __func__, MAC_ADDR_ARRAY(peer), action_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006993 goto error;
Lee Hoonkic1262f22013-01-24 21:59:00 -08006994 }
6995 else
6996 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006997 /* maximum reached. tweak to send error code to peer and return
6998 error code to supplicant */
Lee Hoonkic1262f22013-01-24 21:59:00 -08006999 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007000 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7001 "%s: " MAC_ADDRESS_STR
7002 " TDLS Max peer already connected send response status %d",
7003 __func__, MAC_ADDR_ARRAY(peer), status_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07007004 max_sta_failed = -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007005 /* fall through to send setup resp with failure status
7006 code */
Lee Hoonkic1262f22013-01-24 21:59:00 -08007007 }
7008 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007009 else
7010 {
7011 hddTdlsPeer_t *pTdlsPeer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007012 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007013 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007014 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007015 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07007016 "%s:" MAC_ADDRESS_STR " already connected. action %d declined.",
7017 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007018 return -EPERM;
7019 }
7020 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08007021 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007022 vos_mem_copy(peerMac, peer, 6);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007023
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007024#ifdef WLAN_FEATURE_TDLS_DEBUG
7025 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007026 "%s: " MAC_ADDRESS_STR " action %d, dialog_token %d status %d, len = %d",
7027 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
7028 action_code, dialog_token, status_code, len);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007029#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007030
Hoonki Leea34dd892013-02-05 22:56:02 -08007031 /*Except teardown responder will not be used so just make 0*/
7032 responder = 0;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007033 if (SIR_MAC_TDLS_TEARDOWN == action_code)
Hoonki Leea34dd892013-02-05 22:56:02 -08007034 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007035 responder = wlan_hdd_tdls_get_responder(pAdapter, peerMac);
7036 if(-1 == responder)
Hoonki Leea34dd892013-02-05 22:56:02 -08007037 {
7038 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007039 "%s: " MAC_ADDRESS_STR " peer doesn't exist dialog_token %d status %d, len = %d",
7040 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
Hoonki Leea34dd892013-02-05 22:56:02 -08007041 dialog_token, status_code, len);
7042 return -EPERM;
7043 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007044 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007045
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007046 INIT_COMPLETION(pAdapter->tdls_mgmt_comp);
7047
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007048 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
Hoonki Leea34dd892013-02-05 22:56:02 -08007049 peerMac, action_code, dialog_token, status_code, (tANI_U8 *)buf, len, responder);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007050
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007051 if (VOS_STATUS_SUCCESS != status)
7052 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007053 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7054 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07007055 return -EPERM;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007056 }
7057
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08007058 /* not block discovery request, as it is called from timer callback */
7059 if (SIR_MAC_TDLS_DIS_REQ != action_code)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007060 {
Pervinder Singhb4638422013-03-04 22:51:36 -08007061 long rc;
7062
7063 rc = wait_for_completion_interruptible_timeout(&pAdapter->tdls_mgmt_comp,
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08007064 msecs_to_jiffies(WAIT_TIME_TDLS_MGMT));
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007065
Pervinder Singhb4638422013-03-04 22:51:36 -08007066 if ((rc <= 0) || (TRUE != pAdapter->mgmtTxCompletionStatus))
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08007067 {
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08007068 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pervinder Singhb4638422013-03-04 22:51:36 -08007069 "%s: Mgmt Tx Completion failed status %ld TxCompletion %lu",
7070 __func__, rc, pAdapter->mgmtTxCompletionStatus);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07007071 return -EPERM;
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08007072 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007073 }
7074
Gopichand Nakkala05922802013-03-14 12:23:19 -07007075 if (max_sta_failed)
7076 return max_sta_failed;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007077
Hoonki Leea34dd892013-02-05 22:56:02 -08007078 if (SIR_MAC_TDLS_SETUP_RSP == action_code)
7079 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007080 wlan_hdd_tdls_set_responder(pAdapter, peerMac, TRUE);
Hoonki Leea34dd892013-02-05 22:56:02 -08007081 }
7082 else if (SIR_MAC_TDLS_SETUP_CNF == action_code)
7083 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007084 wlan_hdd_tdls_set_responder(pAdapter, peerMac, FALSE);
Hoonki Leea34dd892013-02-05 22:56:02 -08007085 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007086
7087 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07007088error:
7089 /* max_sta_failed ; we didn't set to CONNECTING for this case,
7090 because we already know that this transaction will be failed,
7091 but we weren't sure if supplicant call DISABLE_LINK or not. So,
7092 to be safe, do not change the state mahine.
7093 */
7094 if(max_sta_failed == 0 &&
7095 (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
7096 wlan_hdd_tdls_set_link_status(pAdapter, peerMac, eTDLS_LINK_IDLE);
7097 return -EPERM;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007098}
7099
7100static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
7101 u8 *peer, enum nl80211_tdls_operation oper)
7102{
7103 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7104 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007105#ifdef WLAN_FEATURE_TDLS_DEBUG
7106 const char *tdls_oper_str[]= {
7107 "NL80211_TDLS_DISCOVERY_REQ",
7108 "NL80211_TDLS_SETUP",
7109 "NL80211_TDLS_TEARDOWN",
7110 "NL80211_TDLS_ENABLE_LINK",
7111 "NL80211_TDLS_DISABLE_LINK",
7112 "NL80211_TDLS_UNKONW_OPER"};
7113#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007114
Chilam Ngc4244af2013-04-01 15:37:32 -07007115 if ( NULL == pHddCtx || NULL == pHddCtx->cfg_ini || NULL == peer )
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007116 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007117 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Chilam Ngc4244af2013-04-01 15:37:32 -07007118 "%s: Invalid arguments", __func__);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007119 return -EINVAL;
7120 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007121
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08007122 if (pHddCtx->isLogpInProgress)
7123 {
7124 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7125 "%s:LOGP in Progress. Ignore!!!", __func__);
7126 return -EBUSY;
7127 }
7128
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007129#ifdef WLAN_FEATURE_TDLS_DEBUG
7130 if((int)oper > 4)
7131 oper = 5;
7132
7133 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007134 "%s: " MAC_ADDRESS_STR " %d (%s) ", "tdls_oper",
7135 MAC_ADDR_ARRAY(peer), (int)oper,
7136 tdls_oper_str[(int)oper]);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007137#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007138
7139 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007140 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007141 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007142 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Chilam Ngc4244af2013-04-01 15:37:32 -07007143 "TDLS Disabled in INI OR not enabled in FW. "
7144 "Cannot process TDLS commands");
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007145 return -ENOTSUPP;
7146 }
7147
7148 switch (oper) {
7149 case NL80211_TDLS_ENABLE_LINK:
7150 {
Hoonki Lee387663d2013-02-05 18:08:43 -08007151 hddTdlsPeer_t *pTdlsPeer;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007152 VOS_STATUS status;
7153
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007154 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007155
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007156 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
7157 "%s: TDLS_LINK_ENABLE " MAC_ADDRESS_STR,
7158 __func__, MAC_ADDR_ARRAY(peer));
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007159
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007160 if ( NULL == pTdlsPeer ) {
7161 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_hdd_tdls_find_peer "
7162 MAC_ADDRESS_STR " failed",
7163 __func__, MAC_ADDR_ARRAY(peer));
7164 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007165 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007166
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007167 if (eTDLS_LINK_CONNECTING == pTdlsPeer->link_status)
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007168 {
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007169 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007170 /* start TDLS client registration with TL */
7171 status = hdd_roamRegisterTDLSSTA( pAdapter, peer, pTdlsPeer->staId, pTdlsPeer->signature);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007172 if (VOS_STATUS_SUCCESS == status)
7173 {
7174 wlan_hdd_tdls_increment_peer_count(pAdapter);
7175 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007176 wlan_hdd_tdls_check_bmps(pAdapter);
7177 }
7178
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007179 }
7180 break;
7181 case NL80211_TDLS_DISABLE_LINK:
Lee Hoonkic1262f22013-01-24 21:59:00 -08007182 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007183 hddTdlsPeer_t *curr_peer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007184
7185 if(NULL != curr_peer)
Lee Hoonkic1262f22013-01-24 21:59:00 -08007186 {
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007187 long status;
7188
7189 INIT_COMPLETION(pAdapter->tdls_del_station_comp);
7190
Lee Hoonkic1262f22013-01-24 21:59:00 -08007191 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
7192 pAdapter->sessionId, peer );
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007193
7194 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_del_station_comp,
7195 msecs_to_jiffies(WAIT_TIME_TDLS_DEL_STA));
7196 if (status <= 0)
7197 {
7198 wlan_hdd_tdls_set_peer_link_status(curr_peer, eTDLS_LINK_IDLE);
7199 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7200 "%s: Del station failed status %ld",
7201 __func__, status);
7202 return -EPERM;
7203 }
Gopichand Nakkala8b00c632013-03-08 19:47:52 -08007204 wlan_hdd_tdls_set_peer_link_status(curr_peer, eTDLS_LINK_IDLE);
Lee Hoonkic1262f22013-01-24 21:59:00 -08007205 }
7206 else
7207 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007208 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7209 "%s: TDLS Peer Station doesn't exist.", __func__);
Lee Hoonkic1262f22013-01-24 21:59:00 -08007210 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08007211 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007212 break;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007213 case NL80211_TDLS_TEARDOWN:
7214 case NL80211_TDLS_SETUP:
7215 case NL80211_TDLS_DISCOVERY_REQ:
7216 /* We don't support in-driver setup/teardown/discovery */
7217 return -ENOTSUPP;
7218 default:
7219 return -ENOTSUPP;
7220 }
7221 return 0;
7222}
Chilam NG571c65a2013-01-19 12:27:36 +05307223
7224int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
7225 struct net_device *dev, u8 *peer)
7226{
7227 hddLog(VOS_TRACE_LEVEL_INFO, "tdls send discover req: %x %x %x %x %x %x",
7228 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5]);
7229
7230 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
7231 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
7232}
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007233#endif
7234
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05307235#ifdef WLAN_FEATURE_GTK_OFFLOAD
7236/*
7237 * FUNCTION: wlan_hdd_cfg80211_update_replayCounterCallback
7238 * Callback rountine called upon receiving response for
7239 * get offload info
7240 */
7241void wlan_hdd_cfg80211_update_replayCounterCallback(void *callbackContext,
7242 tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoRsp)
7243{
7244
7245 hdd_adapter_t *pAdapter = (hdd_adapter_t *)callbackContext;
7246
7247 ENTER();
7248
7249 if (NULL == pAdapter)
7250 {
7251 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7252 "%s: HDD adapter is Null", __func__);
7253 return ;
7254 }
7255
7256 if (NULL == pGtkOffloadGetInfoRsp)
7257 {
7258 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7259 "%s: pGtkOffloadGetInfoRsp is Null", __func__);
7260 return ;
7261 }
7262
7263 if (VOS_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus)
7264 {
7265 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7266 "%s: wlan Failed to get replay counter value",
7267 __func__);
7268 return ;
7269 }
7270
7271 /* Update replay counter to NL */
7272 cfg80211_gtk_rekey_notify(pAdapter->dev, pGtkOffloadGetInfoRsp->bssId,
7273 (tANI_U8 *)&pGtkOffloadGetInfoRsp->ullKeyReplayCounter, GFP_KERNEL);
7274}
7275
7276/*
7277 * FUNCTION: wlan_hdd_cfg80211_set_rekey_data
7278 * This function is used to offload GTK rekeying job to the firmware.
7279 */
7280int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
7281 struct cfg80211_gtk_rekey_data *data)
7282{
7283 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7284 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
7285 hdd_station_ctx_t *pHddStaCtx;
7286 tHalHandle hHal;
7287 tpSirGtkOffloadParams pGtkOffloadReqParams;
7288 eHalStatus status = eHAL_STATUS_FAILURE;
7289
7290 ENTER();
7291
7292 if (NULL == pAdapter)
7293 {
7294 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7295 "%s: HDD adapter is Null", __func__);
7296 return -ENODEV;
7297 }
7298
7299 if (NULL == pHddCtx)
7300 {
7301 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7302 "%s: HDD context is Null!!!", __func__);
7303 return -ENODEV;
7304 }
7305
7306 if (pHddCtx->isLogpInProgress)
7307 {
7308 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7309 "%s: LOGP in Progress. Ignore!!!", __func__);
7310 return -EAGAIN;
7311 }
7312
7313 if (pHddCtx->isLoadUnloadInProgress)
7314 {
7315 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7316 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
7317 return -EAGAIN;
7318 }
7319
7320 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7321 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
7322 if (NULL == hHal)
7323 {
7324 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7325 "%s: HAL context is Null!!!", __func__);
7326 return -EAGAIN;
7327 }
7328
7329 pGtkOffloadReqParams =
7330 &pHddStaCtx->gtkOffloadRequestParams.gtkOffloadReqParams;
7331
7332 pGtkOffloadReqParams->ulFlags = GTK_OFFLOAD_ENABLE;
7333 memcpy(pGtkOffloadReqParams->aKCK, data->kck, NL80211_KCK_LEN);
7334 memcpy(pGtkOffloadReqParams->aKEK, data->kek, NL80211_KEK_LEN);
7335 memcpy(pGtkOffloadReqParams->bssId, &pHddStaCtx->conn_info.bssId,
7336 WNI_CFG_BSSID_LEN);
7337 memcpy(&pGtkOffloadReqParams->ullKeyReplayCounter, &data->replay_ctr,
7338 sizeof (tANI_U64));
7339
7340 if (TRUE == pHddCtx->hdd_wlan_suspended)
7341 {
7342 /* if wlan is suspended, enable GTK offload directly from here */
7343 status = sme_SetGTKOffload(hHal, pGtkOffloadReqParams,
7344 pAdapter->sessionId);
7345
7346 if (eHAL_STATUS_SUCCESS != status)
7347 {
7348 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7349 "%s: sme_SetGTKOffload failed, returned %d",
7350 __func__, status);
7351 return status;
7352 }
7353 pHddStaCtx->gtkOffloadRequestParams.requested = FALSE;
7354 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7355 "%s: sme_SetGTKOffload successfull", __func__);
7356 }
7357 else
7358 {
7359 pHddStaCtx->gtkOffloadRequestParams.requested = TRUE;
7360 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7361 "%s: wlan not suspended GTKOffload request is stored",
7362 __func__);
7363 return eHAL_STATUS_SUCCESS;
7364 }
7365 return status;
7366}
7367#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
7368
Jeff Johnson295189b2012-06-20 16:38:30 -07007369/* cfg80211_ops */
7370static struct cfg80211_ops wlan_hdd_cfg80211_ops =
7371{
7372 .add_virtual_intf = wlan_hdd_add_virtual_intf,
7373 .del_virtual_intf = wlan_hdd_del_virtual_intf,
7374 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
7375 .change_station = wlan_hdd_change_station,
7376#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
7377 .add_beacon = wlan_hdd_cfg80211_add_beacon,
7378 .del_beacon = wlan_hdd_cfg80211_del_beacon,
7379 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007380#else
7381 .start_ap = wlan_hdd_cfg80211_start_ap,
7382 .change_beacon = wlan_hdd_cfg80211_change_beacon,
7383 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07007384#endif
7385 .change_bss = wlan_hdd_cfg80211_change_bss,
7386 .add_key = wlan_hdd_cfg80211_add_key,
7387 .get_key = wlan_hdd_cfg80211_get_key,
7388 .del_key = wlan_hdd_cfg80211_del_key,
7389 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08007390#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07007391 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08007392#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007393 .scan = wlan_hdd_cfg80211_scan,
7394 .connect = wlan_hdd_cfg80211_connect,
7395 .disconnect = wlan_hdd_cfg80211_disconnect,
7396 .join_ibss = wlan_hdd_cfg80211_join_ibss,
7397 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
7398 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
7399 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
7400 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
Jeff Johnson295189b2012-06-20 16:38:30 -07007401 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
7402 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
7403 .mgmt_tx = wlan_hdd_action,
7404#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7405 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
7406 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
7407 .set_txq_params = wlan_hdd_set_txq_params,
7408#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007409 .get_station = wlan_hdd_cfg80211_get_station,
7410 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
7411 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007412 .add_station = wlan_hdd_cfg80211_add_station,
7413#ifdef FEATURE_WLAN_LFR
7414 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
7415 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
7416 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
7417#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007418#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
7419 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
7420#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007421#ifdef FEATURE_WLAN_TDLS
7422 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
7423 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
7424#endif
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05307425#ifdef WLAN_FEATURE_GTK_OFFLOAD
7426 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
7427#endif /* WLAN_FEATURE_GTK_OFFLOAD */
Jeff Johnson295189b2012-06-20 16:38:30 -07007428};
7429