blob: 060b7c142dff26d021c967edadf50ea0c3b87f42 [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
474extern struct net_device_ops net_ops_struct;
475
476/*
477 * FUNCTION: wlan_hdd_cfg80211_init
478 * This function is called by hdd_wlan_startup()
479 * during initialization.
480 * This function is used to initialize and register wiphy structure.
481 */
482struct wiphy *wlan_hdd_cfg80211_init(int priv_size)
483{
484 struct wiphy *wiphy;
485 ENTER();
486
487 /*
488 * Create wiphy device
489 */
490 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
491
492 if (!wiphy)
493 {
494 /* Print error and jump into err label and free the memory */
495 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__);
496 return NULL;
497 }
498
499 return wiphy;
500}
501
502/*
503 * FUNCTION: wlan_hdd_cfg80211_update_band
504 * This function is called from the supplicant through a
505 * private ioctl to change the band value
506 */
507int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
508{
Jeff Johnsone7245742012-09-05 17:12:55 -0700509 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700510 switch(eBand)
511 {
512 case eCSR_BAND_24:
513 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
514 wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
515 break;
516 case eCSR_BAND_5G:
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700517 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700518 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
519 break;
520 case eCSR_BAND_ALL:
521 default:
522 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
523 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
524 }
525 return 0;
526}
527/*
528 * FUNCTION: wlan_hdd_cfg80211_init
529 * This function is called by hdd_wlan_startup()
530 * during initialization.
531 * This function is used to initialize and register wiphy structure.
532 */
533int wlan_hdd_cfg80211_register(struct device *dev,
534 struct wiphy *wiphy,
535 hdd_config_t *pCfg
536 )
537{
Jeff Johnsone7245742012-09-05 17:12:55 -0700538 ENTER();
539
Jeff Johnson295189b2012-06-20 16:38:30 -0700540 /* Now bind the underlying wlan device with wiphy */
541 set_wiphy_dev(wiphy, dev);
542
543 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
544
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700545 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700546
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700547#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700548 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
549 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
550 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
Jeff Johnsone7245742012-09-05 17:12:55 -0700551 | WIPHY_FLAG_OFFCHAN_TX;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700552#endif
James Zmuda77fb5ae2013-01-29 08:00:17 -0800553#ifdef FEATURE_WLAN_LFR
554 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
555#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800556#ifdef FEATURE_WLAN_TDLS
557 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
558 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
559#endif
560
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700561 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
562 driver can still register regulatory callback and
563 it will get CRDA setting in wiphy->band[], but
564 driver need to determine what to do with both
565 regulatory settings */
566 wiphy->reg_notifier = wlan_hdd_crda_reg_notifier;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700567
Jeff Johnson295189b2012-06-20 16:38:30 -0700568 wiphy->max_scan_ssids = MAX_SCAN_SSID;
569
570 wiphy->max_scan_ie_len = 200 ; //TODO: define a macro
571
572 /* Supports STATION & AD-HOC modes right now */
573 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
574 | BIT(NL80211_IFTYPE_ADHOC)
Jeff Johnson295189b2012-06-20 16:38:30 -0700575 | BIT(NL80211_IFTYPE_P2P_CLIENT)
576 | BIT(NL80211_IFTYPE_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -0700577 | BIT(NL80211_IFTYPE_AP);
578
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800579#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800580 if( pCfg->enableMCC )
581 {
582 /* Currently, supports up to two channels */
583 wlan_hdd_iface_combination.num_different_channels = 2;
584
585 if( !pCfg->allowMCCGODiffBI )
586 wlan_hdd_iface_combination.beacon_int_infra_match = true;
587
588 }
589 wiphy->iface_combinations = &wlan_hdd_iface_combination;
590 wiphy->n_iface_combinations = 1;
591#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800592
Jeff Johnson295189b2012-06-20 16:38:30 -0700593 /* Before registering we need to update the ht capabilitied based
594 * on ini values*/
595 if( !pCfg->ShortGI20MhzEnable )
596 {
597 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
598 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
599 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
600 }
601
602 if( !pCfg->ShortGI40MhzEnable )
603 {
604 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
605 }
606
607 if( !pCfg->nChannelBondingMode5GHz )
608 {
609 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
610 }
611
612 /*Initialize band capability*/
613 switch(pCfg->nBandCapability)
614 {
615 case eCSR_BAND_24:
616 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
617 break;
618 case eCSR_BAND_5G:
Jeff Johnson295189b2012-06-20 16:38:30 -0700619 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700620 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
621 break;
622 case eCSR_BAND_ALL:
623 default:
624 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
625 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
626 }
627 /*Initialise the supported cipher suite details*/
628 wiphy->cipher_suites = hdd_cipher_suites;
629 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
630
631 /*signal strength in mBm (100*dBm) */
632 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
633
634#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -0700635 wiphy->max_remain_on_channel_duration = 1000;
636#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700637
638 /* Register our wiphy dev with cfg80211 */
639 if (0 > wiphy_register(wiphy))
640 {
641 /* print eror */
642 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
643 return -EIO;
644 }
645
646 EXIT();
647 return 0;
648}
649
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700650/* In this function we will try to get default country code from crda.
651 If the gCrdaDefaultCountryCode is configured in ini file,
652 we will try to call user space crda to get the regulatory settings for
653 that country. We will timeout if we can't get it from crda.
654 It's called by hdd_wlan_startup() after wlan_hdd_cfg80211_register.
655*/
656int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg)
657{
658 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
659 if (memcmp(pCfg->crdaDefaultCountryCode,
660 CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) != 0)
661 {
662 init_completion(&pHddCtx->driver_crda_req);
663 regulatory_hint(wiphy, pCfg->crdaDefaultCountryCode);
664 wait_for_completion_interruptible_timeout(&pHddCtx->driver_crda_req,
665 CRDA_WAIT_TIME);
666 }
667 return 0;
668}
669
Jeff Johnson295189b2012-06-20 16:38:30 -0700670/* In this function we will do all post VOS start initialization.
671 In this function we will register for all frame in which supplicant
672 is interested.
673*/
674void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
675{
Jeff Johnson295189b2012-06-20 16:38:30 -0700676 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
677 /* Register for all P2P action, public action etc frames */
678 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
679
Jeff Johnsone7245742012-09-05 17:12:55 -0700680 ENTER();
681
Jeff Johnson295189b2012-06-20 16:38:30 -0700682 /* Right now we are registering these frame when driver is getting
683 initialized. Once we will move to 2.6.37 kernel, in which we have
684 frame register ops, we will move this code as a part of that */
685 /* GAS Initial Request */
686 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
687 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
688
689 /* GAS Initial Response */
690 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
691 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
692
693 /* GAS Comeback Request */
694 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
695 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
696
697 /* GAS Comeback Response */
698 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
699 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
700
701 /* P2P Public Action */
702 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
703 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
704 P2P_PUBLIC_ACTION_FRAME_SIZE );
705
706 /* P2P Action */
707 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
708 (v_U8_t*)P2P_ACTION_FRAME,
709 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -0700710
711#ifdef WLAN_FEATURE_11W
712 /* SA Query Response Action Frame */
713 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
714 (v_U8_t*)SA_QUERY_FRAME_RSP,
715 SA_QUERY_FRAME_RSP_SIZE );
716#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -0700717}
718
719void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
720{
Jeff Johnson295189b2012-06-20 16:38:30 -0700721 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
722 /* Register for all P2P action, public action etc frames */
723 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
724
Jeff Johnsone7245742012-09-05 17:12:55 -0700725 ENTER();
726
Jeff Johnson295189b2012-06-20 16:38:30 -0700727 /* Right now we are registering these frame when driver is getting
728 initialized. Once we will move to 2.6.37 kernel, in which we have
729 frame register ops, we will move this code as a part of that */
730 /* GAS Initial Request */
731
732 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
733 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
734
735 /* GAS Initial Response */
736 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
737 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
738
739 /* GAS Comeback Request */
740 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
741 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
742
743 /* GAS Comeback Response */
744 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
745 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
746
747 /* P2P Public Action */
748 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
749 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
750 P2P_PUBLIC_ACTION_FRAME_SIZE );
751
752 /* P2P Action */
753 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
754 (v_U8_t*)P2P_ACTION_FRAME,
755 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -0700756
757#ifdef WLAN_FEATURE_11W
758 /* SA Query Response Action Frame */
759 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
760 (v_U8_t*)SA_QUERY_FRAME_RSP,
761 SA_QUERY_FRAME_RSP_SIZE );
762#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -0700763}
764
765#ifdef FEATURE_WLAN_WAPI
766void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
767 const u8 *mac_addr, u8 *key , int key_Len)
768{
769 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
770 tCsrRoamSetKey setKey;
771 v_BOOL_t isConnected = TRUE;
772 int status = 0;
773 v_U32_t roamId= 0xFF;
774 tANI_U8 *pKeyPtr = NULL;
775 int n = 0;
776
777 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
778 __func__,pAdapter->device_mode);
779
Gopichand Nakkalae7480202013-02-11 15:24:22 +0530780 vos_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Jeff Johnson295189b2012-06-20 16:38:30 -0700781 setKey.keyId = key_index; // Store Key ID
782 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
783 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
784 setKey.paeRole = 0 ; // the PAE role
785 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
786 {
787 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
788 }
789 else
790 {
791 isConnected = hdd_connIsConnected(pHddStaCtx);
792 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
793 }
794 setKey.keyLength = key_Len;
795 pKeyPtr = setKey.Key;
796 memcpy( pKeyPtr, key, key_Len);
797
798 hddLog(VOS_TRACE_LEVEL_INFO,"\n%s: WAPI KEY LENGTH:0x%04x",
799 __func__, key_Len);
800 for (n = 0 ; n < key_Len; n++)
801 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
802 __func__,n,setKey.Key[n]);
803
804 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
805 if ( isConnected )
806 {
807 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
808 pAdapter->sessionId, &setKey, &roamId );
809 }
810 if ( status != 0 )
811 {
812 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
813 "[%4d] sme_RoamSetKey returned ERROR status= %d",
814 __LINE__, status );
815 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
816 }
817}
818#endif /* FEATURE_WLAN_WAPI*/
819
820#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
821int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
822 beacon_data_t **ppBeacon,
823 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700824#else
825int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
826 beacon_data_t **ppBeacon,
827 struct cfg80211_beacon_data *params,
828 int dtim_period)
829#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700830{
831 int size;
832 beacon_data_t *beacon = NULL;
833 beacon_data_t *old = NULL;
834 int head_len,tail_len;
835
Jeff Johnsone7245742012-09-05 17:12:55 -0700836 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700837 if (params->head && !params->head_len)
838 return -EINVAL;
839
840 old = pAdapter->sessionCtx.ap.beacon;
841
842 if (!params->head && !old)
843 return -EINVAL;
844
845 if (params->tail && !params->tail_len)
846 return -EINVAL;
847
848#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
849 /* Kernel 3.0 is not updating dtim_period for set beacon */
850 if (!params->dtim_period)
851 return -EINVAL;
852#endif
853
854 if(params->head)
855 head_len = params->head_len;
856 else
857 head_len = old->head_len;
858
859 if(params->tail || !old)
860 tail_len = params->tail_len;
861 else
862 tail_len = old->tail_len;
863
864 size = sizeof(beacon_data_t) + head_len + tail_len;
865
866 beacon = kzalloc(size, GFP_KERNEL);
867
868 if( beacon == NULL )
869 return -ENOMEM;
870
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700871#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700872 if(params->dtim_period || !old )
873 beacon->dtim_period = params->dtim_period;
874 else
875 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700876#else
877 if(dtim_period || !old )
878 beacon->dtim_period = dtim_period;
879 else
880 beacon->dtim_period = old->dtim_period;
881#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700882
883 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
884 beacon->tail = beacon->head + head_len;
885 beacon->head_len = head_len;
886 beacon->tail_len = tail_len;
887
888 if(params->head) {
889 memcpy (beacon->head,params->head,beacon->head_len);
890 }
891 else {
892 if(old)
893 memcpy (beacon->head,old->head,beacon->head_len);
894 }
895
896 if(params->tail) {
897 memcpy (beacon->tail,params->tail,beacon->tail_len);
898 }
899 else {
900 if(old)
901 memcpy (beacon->tail,old->tail,beacon->tail_len);
902 }
903
904 *ppBeacon = beacon;
905
906 kfree(old);
907
908 return 0;
909
910}
Jeff Johnson295189b2012-06-20 16:38:30 -0700911
912v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
913{
914 int left = length;
915 v_U8_t *ptr = pIes;
916 v_U8_t elem_id,elem_len;
917
918 while(left >= 2)
919 {
920 elem_id = ptr[0];
921 elem_len = ptr[1];
922 left -= 2;
923 if(elem_len > left)
924 {
925 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700926 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -0700927 eid,elem_len,left);
928 return NULL;
929 }
930 if (elem_id == eid)
931 {
932 return ptr;
933 }
934
935 left -= elem_len;
936 ptr += (elem_len + 2);
937 }
938 return NULL;
939}
940
Jeff Johnson295189b2012-06-20 16:38:30 -0700941/* Check if rate is 11g rate or not */
942static int wlan_hdd_rate_is_11g(u8 rate)
943{
944 u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 104}; /* actual rate * 2 */
945 u8 i;
946 for (i = 0; i < 8; i++)
947 {
948 if(rate == gRateArray[i])
949 return TRUE;
950 }
951 return FALSE;
952}
953
954/* Check for 11g rate and set proper 11g only mode */
955static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
956 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
957{
958 u8 i, num_rates = pIe[0];
959
960 pIe += 1;
961 for ( i = 0; i < num_rates; i++)
962 {
963 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
964 {
965 /* If rate set have 11g rate than change the mode to 11G */
966 *pSapHw_mode = eSAP_DOT11_MODE_11g;
967 if (pIe[i] & BASIC_RATE_MASK)
968 {
969 /* If we have 11g rate as basic rate, it means mode
970 is 11g only mode.
971 */
972 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
973 *pCheckRatesfor11g = FALSE;
974 }
975 }
976 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
977 {
978 *require_ht = TRUE;
979 }
980 }
981 return;
982}
983
984static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
985{
986 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
987 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
988 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
989 u8 checkRatesfor11g = TRUE;
990 u8 require_ht = FALSE;
991 u8 *pIe=NULL;
992
993 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
994
995 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
996 pBeacon->head_len, WLAN_EID_SUPP_RATES);
997 if (pIe != NULL)
998 {
999 pIe += 1;
1000 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1001 &pConfig->SapHw_mode);
1002 }
1003
1004 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1005 WLAN_EID_EXT_SUPP_RATES);
1006 if (pIe != NULL)
1007 {
1008
1009 pIe += 1;
1010 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1011 &pConfig->SapHw_mode);
1012 }
1013
1014 if( pConfig->channel > 14 )
1015 {
1016 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
1017 }
1018
1019 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1020 WLAN_EID_HT_CAPABILITY);
1021
1022 if(pIe)
1023 {
1024 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
1025 if(require_ht)
1026 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
1027 }
1028}
1029
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301030static int wlan_hdd_add_ie(hdd_adapter_t* pHostapdAdapter, v_U8_t *genie,
1031 v_U8_t *total_ielen, v_U8_t *oui, v_U8_t oui_size)
1032{
1033 v_U8_t ielen = 0;
1034 v_U8_t *pIe = NULL;
1035 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1036
1037 pIe = wlan_hdd_get_vendor_oui_ie_ptr(oui, oui_size,
1038 pBeacon->tail, pBeacon->tail_len);
1039
1040 if (pIe)
1041 {
1042 ielen = pIe[1] + 2;
1043 if ((*total_ielen + ielen) <= MAX_GENIE_LEN)
1044 {
1045 vos_mem_copy(&genie[*total_ielen], pIe, ielen);
1046 }
1047 else
1048 {
1049 hddLog( VOS_TRACE_LEVEL_ERROR, "**Ie Length is too big***");
1050 return -EINVAL;
1051 }
1052 *total_ielen += ielen;
1053 }
1054 return 0;
1055}
1056
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001057#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001058static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1059 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001060#else
1061static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1062 struct cfg80211_beacon_data *params)
1063#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001064{
1065 v_U8_t *genie;
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301066 v_U8_t total_ielen = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001067 v_U8_t addIE[1] = {0};
Jeff Johnsone7245742012-09-05 17:12:55 -07001068 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001069
1070 genie = vos_mem_malloc(MAX_GENIE_LEN);
1071
1072 if(genie == NULL) {
1073
1074 return -ENOMEM;
1075 }
1076
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301077 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1078 &total_ielen, WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001079 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301080 ret = -EINVAL;
1081 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001082 }
1083
1084#ifdef WLAN_FEATURE_WFD
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301085 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1086 &total_ielen, WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE))
1087 {
1088 ret = -EINVAL;
1089 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001090 }
1091#endif
1092
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301093 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1094 &total_ielen, P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001095 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301096 ret = -EINVAL;
1097 goto done;
1098 }
1099
1100 if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode)
1101 {
1102 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1103 &total_ielen, SS_OUI_TYPE, SS_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001104 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301105 ret = -EINVAL;
1106 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001107 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001108 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001109
1110 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1111 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1112 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1113 {
1114 hddLog(LOGE,
1115 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001116 ret = -EINVAL;
1117 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001118 }
1119
1120 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1121 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1122 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1123 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1124 ==eHAL_STATUS_FAILURE)
1125 {
1126 hddLog(LOGE,
1127 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001128 ret = -EINVAL;
1129 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001130 }
1131
1132 // Added for ProResp IE
1133 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1134 {
1135 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1136 u8 probe_rsp_ie_len[3] = {0};
1137 u8 counter = 0;
1138 /* Check Probe Resp Length if it is greater then 255 then Store
1139 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1140 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1141 Store More then 255 bytes into One Variable.
1142 */
1143 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1144 {
1145 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1146 {
1147 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1148 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1149 }
1150 else
1151 {
1152 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1153 rem_probe_resp_ie_len = 0;
1154 }
1155 }
1156
1157 rem_probe_resp_ie_len = 0;
1158
1159 if (probe_rsp_ie_len[0] > 0)
1160 {
1161 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1162 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1163 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1164 probe_rsp_ie_len[0], NULL,
1165 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1166 {
1167 hddLog(LOGE,
1168 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001169 ret = -EINVAL;
1170 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001171 }
1172 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1173 }
1174
1175 if (probe_rsp_ie_len[1] > 0)
1176 {
1177 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1178 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1179 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1180 probe_rsp_ie_len[1], NULL,
1181 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1182 {
1183 hddLog(LOGE,
1184 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001185 ret = -EINVAL;
1186 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001187 }
1188 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1189 }
1190
1191 if (probe_rsp_ie_len[2] > 0)
1192 {
1193 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1194 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1195 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1196 probe_rsp_ie_len[2], NULL,
1197 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1198 {
1199 hddLog(LOGE,
1200 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001201 ret = -EINVAL;
1202 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001203 }
1204 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1205 }
1206
1207 if (probe_rsp_ie_len[1] == 0 )
1208 {
1209 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1210 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1211 eANI_BOOLEAN_FALSE) )
1212 {
1213 hddLog(LOGE,
1214 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1215 }
1216 }
1217
1218 if (probe_rsp_ie_len[2] == 0 )
1219 {
1220 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1221 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1222 eANI_BOOLEAN_FALSE) )
1223 {
1224 hddLog(LOGE,
1225 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1226 }
1227 }
1228
1229 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1230 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1231 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1232 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1233 == eHAL_STATUS_FAILURE)
1234 {
1235 hddLog(LOGE,
1236 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001237 ret = -EINVAL;
1238 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001239 }
1240 }
1241 else
1242 {
1243 // Reset WNI_CFG_PROBE_RSP Flags
1244 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1245
1246 hddLog(VOS_TRACE_LEVEL_INFO,
1247 "%s: No Probe Response IE received in set beacon",
1248 __func__);
1249 }
1250
1251 // Added for AssocResp IE
1252 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1253 {
1254 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1255 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1256 params->assocresp_ies_len, NULL,
1257 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1258 {
1259 hddLog(LOGE,
1260 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001261 ret = -EINVAL;
1262 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001263 }
1264
1265 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1266 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1267 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1268 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1269 == eHAL_STATUS_FAILURE)
1270 {
1271 hddLog(LOGE,
1272 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001273 ret = -EINVAL;
1274 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001275 }
1276 }
1277 else
1278 {
1279 hddLog(VOS_TRACE_LEVEL_INFO,
1280 "%s: No Assoc Response IE received in set beacon",
1281 __func__);
1282
1283 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1284 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1285 eANI_BOOLEAN_FALSE) )
1286 {
1287 hddLog(LOGE,
1288 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1289 }
1290 }
1291
Jeff Johnsone7245742012-09-05 17:12:55 -07001292done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001293 vos_mem_free(genie);
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301294 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07001295}
Jeff Johnson295189b2012-06-20 16:38:30 -07001296
1297/*
1298 * FUNCTION: wlan_hdd_validate_operation_channel
1299 * called by wlan_hdd_cfg80211_start_bss() and
1300 * wlan_hdd_cfg80211_set_channel()
1301 * This function validates whether given channel is part of valid
1302 * channel list.
1303 */
1304static VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
1305{
1306
1307 v_U32_t num_ch = 0;
1308 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1309 u32 indx = 0;
1310 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301311 v_U8_t fValidChannel = FALSE, count = 0;
1312 hdd_config_t *hdd_pConfig_ini= (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07001313
1314 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1315
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301316 if ( hdd_pConfig_ini->sapAllowAllChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001317 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301318 /* Validate the channel */
1319 for (count = RF_CHAN_1 ; count <= RF_CHAN_165 ; count++)
Jeff Johnson295189b2012-06-20 16:38:30 -07001320 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301321 if ( channel == rfChannels[count].channelNum )
1322 {
1323 fValidChannel = TRUE;
1324 break;
1325 }
1326 }
1327 if (fValidChannel != TRUE)
1328 {
1329 hddLog(VOS_TRACE_LEVEL_ERROR,
1330 "%s: Invalid Channel [%d]", __func__, channel);
1331 return VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001332 }
1333 }
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301334 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001335 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301336 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1337 valid_ch, &num_ch))
1338 {
1339 hddLog(VOS_TRACE_LEVEL_ERROR,
1340 "%s: failed to get valid channel list", __func__);
1341 return VOS_STATUS_E_FAILURE;
1342 }
1343 for (indx = 0; indx < num_ch; indx++)
1344 {
1345 if (channel == valid_ch[indx])
1346 {
1347 break;
1348 }
1349 }
1350
1351 if (indx >= num_ch)
1352 {
1353 hddLog(VOS_TRACE_LEVEL_ERROR,
1354 "%s: Invalid Channel [%d]", __func__, channel);
1355 return VOS_STATUS_E_FAILURE;
1356 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001357 }
1358 return VOS_STATUS_SUCCESS;
1359
1360}
1361
Viral Modi3a32cc52013-02-08 11:14:52 -08001362/**
1363 * FUNCTION: wlan_hdd_cfg80211_set_channel
1364 * This function is used to set the channel number
1365 */
1366static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
1367 struct ieee80211_channel *chan,
1368 enum nl80211_channel_type channel_type
1369 )
1370{
1371 v_U32_t num_ch = 0;
Jeff Johnson4416a782013-03-25 14:17:50 -07001372 int channel = 0;
Viral Modi3a32cc52013-02-08 11:14:52 -08001373 hdd_adapter_t *pAdapter = NULL;
1374 int freq = chan->center_freq; /* freq is in MHZ */
1375
1376 ENTER();
1377
1378 if( NULL == dev )
1379 {
1380 hddLog(VOS_TRACE_LEVEL_ERROR,
1381 "%s: Called with dev = NULL.\n", __func__);
1382 return -ENODEV;
1383 }
1384 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1385
1386 hddLog(VOS_TRACE_LEVEL_INFO,
1387 "%s: device_mode = %d freq = %d \n",__func__,
1388 pAdapter->device_mode, chan->center_freq);
1389 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1390 {
1391 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1392 return -EAGAIN;
1393 }
1394
1395 /*
1396 * Do freq to chan conversion
1397 * TODO: for 11a
1398 */
1399
1400 channel = ieee80211_frequency_to_channel(freq);
1401
1402 /* Check freq range */
1403 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
1404 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
1405 {
1406 hddLog(VOS_TRACE_LEVEL_ERROR,
1407 "%s: Channel [%d] is outside valid range from %d to %d\n",
1408 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
1409 WNI_CFG_CURRENT_CHANNEL_STAMAX);
1410 return -EINVAL;
1411 }
1412
1413 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1414
Gopichand Nakkala6ab19562013-03-07 13:59:42 +05301415 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode) &&
1416 (WLAN_HDD_P2P_GO != pAdapter->device_mode))
Viral Modi3a32cc52013-02-08 11:14:52 -08001417 {
1418 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
1419 {
1420 hddLog(VOS_TRACE_LEVEL_ERROR,
1421 "%s: Invalid Channel [%d] \n", __func__, channel);
1422 return -EINVAL;
1423 }
1424 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1425 "%s: set channel to [%d] for device mode =%d",
1426 __func__, channel,pAdapter->device_mode);
1427 }
1428 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Viral Modi3a32cc52013-02-08 11:14:52 -08001429 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Viral Modi3a32cc52013-02-08 11:14:52 -08001430 )
1431 {
1432 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
1433 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
1434 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1435
1436 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
1437 {
1438 /* Link is up then return cant set channel*/
1439 hddLog( VOS_TRACE_LEVEL_ERROR,
1440 "%s: IBSS Associated, can't set the channel\n", __func__);
1441 return -EINVAL;
1442 }
1443
1444 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
1445 pHddStaCtx->conn_info.operationChannel = channel;
1446 pRoamProfile->ChannelInfo.ChannelList =
1447 &pHddStaCtx->conn_info.operationChannel;
1448 }
1449 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Viral Modi3a32cc52013-02-08 11:14:52 -08001450 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Viral Modi3a32cc52013-02-08 11:14:52 -08001451 )
1452 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301453 if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
1454 {
1455 if(VOS_STATUS_SUCCESS !=
1456 wlan_hdd_validate_operation_channel(pAdapter,channel))
1457 {
1458 hddLog(VOS_TRACE_LEVEL_ERROR,
1459 "%s: Invalid Channel [%d] \n", __func__, channel);
1460 return -EINVAL;
1461 }
1462 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1463 }
1464 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
Viral Modi3a32cc52013-02-08 11:14:52 -08001465 {
1466 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
1467
1468 /* If auto channel selection is configured as enable/ 1 then ignore
1469 channel set by supplicant
1470 */
1471 if ( cfg_param->apAutoChannelSelection )
1472 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301473 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel =
1474 AUTO_CHANNEL_SELECT;
Viral Modi3a32cc52013-02-08 11:14:52 -08001475 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1476 "%s: set channel to auto channel (0) for device mode =%d",
1477 __func__, pAdapter->device_mode);
1478 }
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301479 else
1480 {
1481 if(VOS_STATUS_SUCCESS !=
1482 wlan_hdd_validate_operation_channel(pAdapter,channel))
1483 {
1484 hddLog(VOS_TRACE_LEVEL_ERROR,
1485 "%s: Invalid Channel [%d] \n", __func__, channel);
1486 return -EINVAL;
1487 }
1488 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1489 }
Viral Modi3a32cc52013-02-08 11:14:52 -08001490 }
1491 }
1492 else
1493 {
1494 hddLog(VOS_TRACE_LEVEL_FATAL,
1495 "%s: Invalid device mode failed to set valid channel", __func__);
1496 return -EINVAL;
1497 }
1498 EXIT();
1499 return 0;
1500}
1501
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301502/*
1503 * FUNCTION: wlan_hdd_select_cbmode
1504 * called by wlan_hdd_cfg80211_start_bss() and
1505 * This function selects the cbmode based on primary channel
1506 */
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001507VOS_STATUS wlan_sap_select_cbmode(void *pAdapter,eSapPhyMode SapHw_mode, v_U8_t channel)
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301508{
1509 tSmeConfigParams smeConfig;
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001510 hdd_context_t *pHddCtx = ( hdd_context_t *) pAdapter;
1511 hdd_config_t *pConfigIni = ((hdd_context_t *)(pAdapter))->cfg_ini;
1512
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301513 if(
1514#ifdef WLAN_FEATURE_11AC
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001515 SapHw_mode != eSAP_DOT11_MODE_11ac &&
1516 SapHw_mode != eSAP_DOT11_MODE_11ac_ONLY &&
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301517#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001518 SapHw_mode != eSAP_DOT11_MODE_11n &&
1519 SapHw_mode != eSAP_DOT11_MODE_11n_ONLY
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301520 )
1521 {
1522 return VOS_STATUS_SUCCESS;
1523 }
1524
1525 if (!pConfigIni->nChannelBondingMode5GHz) {
1526 return VOS_STATUS_SUCCESS;
1527 }
1528
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001529 //channel = pSapConfig->channel;
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301530 vos_mem_zero(&smeConfig, sizeof (tSmeConfigParams));
1531
1532 sme_GetConfigParam(pHddCtx->hHal, &smeConfig);
1533
1534#ifdef WLAN_FEATURE_11AC
1535
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001536 if ( SapHw_mode == eSAP_DOT11_MODE_11ac ||
1537 SapHw_mode == eSAP_DOT11_MODE_11ac_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301538 {
1539 if ( channel== 36 || channel == 52 || channel == 100 ||
1540 channel == 116 || channel == 149 )
1541 {
1542 smeConfig.csrConfig.channelBondingMode5GHz =
1543 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW - 1;
1544 }
1545 else if ( channel == 40 || channel == 56 || channel == 104 ||
1546 channel == 120 || channel == 153 )
1547 {
1548 smeConfig.csrConfig.channelBondingMode5GHz =
1549 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW - 1;
1550 }
1551 else if ( channel == 44 || channel == 60 || channel == 108 ||
1552 channel == 124 || channel == 157 )
1553 {
1554 smeConfig.csrConfig.channelBondingMode5GHz =
1555 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH -1;
1556 }
1557 else if ( channel == 48 || channel == 64 || channel == 112 ||
1558 channel == 128 || channel == 161 )
1559 {
1560 smeConfig.csrConfig.channelBondingMode5GHz =
1561 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH - 1;
1562 }
Shailender Karmuchi84f11f02013-02-12 17:11:45 -08001563 else if ( channel == 165 )
1564 {
1565 smeConfig.csrConfig.channelBondingMode5GHz = 0;
1566 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301567 }
1568#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001569 if ( SapHw_mode == eSAP_DOT11_MODE_11n ||
1570 SapHw_mode == eSAP_DOT11_MODE_11n_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301571 {
1572 if ( channel== 40 || channel == 48 || channel == 56 ||
1573 channel == 64 || channel == 104 || channel == 112 ||
1574 channel == 120 || channel == 128 || channel == 136 ||
1575 channel == 144 || channel == 153 || channel == 161 )
1576 {
1577 smeConfig.csrConfig.channelBondingMode5GHz = 1;
1578 }
1579 else if ( channel== 36 || channel == 44 || channel == 52 ||
1580 channel == 60 || channel == 100 || channel == 108 ||
1581 channel == 116 || channel == 124 || channel == 132 ||
1582 channel == 140 || channel == 149 || channel == 157 )
1583 {
1584 smeConfig.csrConfig.channelBondingMode5GHz = 2;
1585 }
Shailender Karmuchi84f11f02013-02-12 17:11:45 -08001586 else if ( channel == 165 )
1587 {
1588 smeConfig.csrConfig.channelBondingMode5GHz = 0;
1589 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301590 }
1591 pr_info ("cbmode selected=%ld\n",smeConfig.csrConfig.channelBondingMode5GHz);
1592
1593 sme_UpdateConfig (pHddCtx->hHal,&smeConfig);
1594 return VOS_STATUS_SUCCESS;
1595}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001596
Jeff Johnson295189b2012-06-20 16:38:30 -07001597#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1598static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1599 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001600#else
1601static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1602 struct cfg80211_beacon_data *params,
1603 const u8 *ssid, size_t ssid_len,
1604 enum nl80211_hidden_ssid hidden_ssid)
1605#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001606{
1607 tsap_Config_t *pConfig;
1608 beacon_data_t *pBeacon = NULL;
1609 struct ieee80211_mgmt *pMgmt_frame;
1610 v_U8_t *pIe=NULL;
1611 v_U16_t capab_info;
1612 eCsrAuthType RSNAuthType;
1613 eCsrEncryptionType RSNEncryptType;
1614 eCsrEncryptionType mcRSNEncryptType;
1615 int status = VOS_STATUS_SUCCESS;
1616 tpWLAN_SAPEventCB pSapEventCallback;
1617 hdd_hostapd_state_t *pHostapdState;
1618 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1619 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301620 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001621 struct qc_mac_acl_entry *acl_entry = NULL;
1622 v_SINT_t i;
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001623 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001624
1625 ENTER();
1626
1627 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1628
1629 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1630
1631 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1632
1633 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1634
1635 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1636
1637 //channel is already set in the set_channel Call back
1638 //pConfig->channel = pCommitConfig->channel;
1639
1640 /*Protection parameter to enable or disable*/
1641 pConfig->protEnabled =
1642 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1643
1644 pConfig->dtim_period = pBeacon->dtim_period;
1645
1646 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1647 pConfig->dtim_period);
1648
1649
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001650 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001651 {
1652 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001653 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001654 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001655 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001656 tANI_BOOLEAN restartNeeded;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001657 pConfig->ieee80211d = 1;
1658 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1659 sme_setRegInfo(hHal, pConfig->countryCode);
1660 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
Jeff Johnson295189b2012-06-20 16:38:30 -07001661 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001662 else
1663 {
1664 pConfig->ieee80211d = 0;
1665 }
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301666 /*
1667 * If auto channel is configured i.e. channel is 0,
1668 * so skip channel validation.
1669 */
1670 if( AUTO_CHANNEL_SELECT != pConfig->channel )
1671 {
1672 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1673 {
1674 hddLog(VOS_TRACE_LEVEL_ERROR,
1675 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1676 return -EINVAL;
1677 }
1678 }
1679 else
1680 {
1681 if(1 != pHddCtx->is_dynamic_channel_range_set)
1682 {
1683 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
1684 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
1685 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
1686 }
1687 pHddCtx->is_dynamic_channel_range_set = 0;
1688 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001689 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001690 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001691 {
1692 pConfig->ieee80211d = 0;
1693 }
1694 pConfig->authType = eSAP_AUTO_SWITCH;
1695
1696 capab_info = pMgmt_frame->u.beacon.capab_info;
1697
1698 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
1699 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1700
1701 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1702
1703 /*Set wps station to configured*/
1704 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1705
1706 if(pIe)
1707 {
1708 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1709 {
1710 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1711 return -EINVAL;
1712 }
1713 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1714 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001715 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001716 /* Check 15 bit of WPS IE as it contain information for wps state
1717 * WPS state
1718 */
1719 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1720 {
1721 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1722 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1723 {
1724 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1725 }
1726 }
1727 }
1728 else
1729 {
1730 pConfig->wps_state = SAP_WPS_DISABLED;
1731 }
1732 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
1733
1734 pConfig->RSNWPAReqIELength = 0;
1735 pConfig->pRSNWPAReqIE = NULL;
1736 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1737 WLAN_EID_RSN);
1738 if(pIe && pIe[1])
1739 {
1740 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1741 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1742 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1743 /* The actual processing may eventually be more extensive than
1744 * this. Right now, just consume any PMKIDs that are sent in
1745 * by the app.
1746 * */
1747 status = hdd_softap_unpackIE(
1748 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1749 &RSNEncryptType,
1750 &mcRSNEncryptType,
1751 &RSNAuthType,
1752 pConfig->pRSNWPAReqIE[1]+2,
1753 pConfig->pRSNWPAReqIE );
1754
1755 if( VOS_STATUS_SUCCESS == status )
1756 {
1757 /* Now copy over all the security attributes you have
1758 * parsed out
1759 * */
1760 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1761 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1762 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1763 = RSNEncryptType;
1764 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1765 "EncryptionType = %d mcEncryptionType = %d\n"),
1766 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1767 }
1768 }
1769
1770 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1771 pBeacon->tail, pBeacon->tail_len);
1772
1773 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1774 {
1775 if (pConfig->pRSNWPAReqIE)
1776 {
1777 /*Mixed mode WPA/WPA2*/
1778 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1779 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1780 }
1781 else
1782 {
1783 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1784 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1785 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1786 status = hdd_softap_unpackIE(
1787 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1788 &RSNEncryptType,
1789 &mcRSNEncryptType,
1790 &RSNAuthType,
1791 pConfig->pRSNWPAReqIE[1]+2,
1792 pConfig->pRSNWPAReqIE );
1793
1794 if( VOS_STATUS_SUCCESS == status )
1795 {
1796 /* Now copy over all the security attributes you have
1797 * parsed out
1798 * */
1799 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1800 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1801 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1802 = RSNEncryptType;
1803 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1804 "EncryptionType = %d mcEncryptionType = %d\n"),
1805 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1806 }
1807 }
1808 }
1809
Jeff Johnson4416a782013-03-25 14:17:50 -07001810 if (pConfig->RSNWPAReqIELength > sizeof wpaRsnIEdata) {
1811 hddLog( VOS_TRACE_LEVEL_ERROR, "**RSNWPAReqIELength is too large***");
1812 return -EINVAL;
1813 }
1814
Jeff Johnson295189b2012-06-20 16:38:30 -07001815 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1816
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001817#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001818 if (params->ssid != NULL)
1819 {
1820 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1821 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1822 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1823 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1824 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001825#else
1826 if (ssid != NULL)
1827 {
1828 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1829 pConfig->SSIDinfo.ssid.length = ssid_len;
1830 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1831 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1832 }
1833#endif
1834
Jeff Johnson295189b2012-06-20 16:38:30 -07001835 vos_mem_copy(pConfig->self_macaddr.bytes,
1836 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1837
1838 /* default value */
1839 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1840 pConfig->num_accept_mac = 0;
1841 pConfig->num_deny_mac = 0;
1842
1843 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1844 pBeacon->tail, pBeacon->tail_len);
1845
1846 /* pIe for black list is following form:
1847 type : 1 byte
1848 length : 1 byte
1849 OUI : 4 bytes
1850 acl type : 1 byte
1851 no of mac addr in black list: 1 byte
1852 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1853 */
1854 if ((pIe != NULL) && (pIe[1] != 0))
1855 {
1856 pConfig->SapMacaddr_acl = pIe[6];
1857 pConfig->num_deny_mac = pIe[7];
1858 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1859 pIe[6], pIe[7]);
1860 if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
1861 pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
1862 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1863 for (i = 0; i < pConfig->num_deny_mac; i++)
1864 {
1865 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1866 acl_entry++;
1867 }
1868 }
1869 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1870 pBeacon->tail, pBeacon->tail_len);
1871
1872 /* pIe for white list is following form:
1873 type : 1 byte
1874 length : 1 byte
1875 OUI : 4 bytes
1876 acl type : 1 byte
1877 no of mac addr in white list: 1 byte
1878 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1879 */
1880 if ((pIe != NULL) && (pIe[1] != 0))
1881 {
1882 pConfig->SapMacaddr_acl = pIe[6];
1883 pConfig->num_accept_mac = pIe[7];
1884 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
1885 pIe[6], pIe[7]);
1886 if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
1887 pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
1888 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1889 for (i = 0; i < pConfig->num_accept_mac; i++)
1890 {
1891 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1892 acl_entry++;
1893 }
1894 }
1895 wlan_hdd_set_sapHwmode(pHostapdAdapter);
1896
Jeff Johnsone7245742012-09-05 17:12:55 -07001897#ifdef WLAN_FEATURE_11AC
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08001898 /* Overwrite the hostapd setting for HW mode only for 11ac.
1899 * This is valid only if mode is set to 11n in hostapd and either AUTO or 11ac in .ini .
1900 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode) */
1901 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
1902 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
1903 (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
1904 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1905 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07001906 {
1907 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
1908 }
1909#endif
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301910
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001911 if( AUTO_CHANNEL_SELECT != pConfig->channel)
1912 wlan_sap_select_cbmode((WLAN_HDD_GET_CTX(pHostapdAdapter)),pConfig->SapHw_mode,pConfig->channel);
Jeff Johnson295189b2012-06-20 16:38:30 -07001913 // ht_capab is not what the name conveys,this is used for protection bitmap
1914 pConfig->ht_capab =
1915 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
1916
1917 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
1918 {
1919 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
1920 return -EINVAL;
1921 }
1922
1923 //Uapsd Enabled Bit
1924 pConfig->UapsdEnable =
1925 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
1926 //Enable OBSS protection
1927 pConfig->obssProtEnabled =
1928 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
1929
1930 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
1931 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
1932 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
1933 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
1934 (int)pConfig->channel);
1935 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
1936 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
1937 pConfig->authType);
1938 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
1939 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
1940 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
1941 pConfig->protEnabled, pConfig->obssProtEnabled);
1942
1943 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
1944 {
1945 //Bss already started. just return.
1946 //TODO Probably it should update some beacon params.
1947 hddLog( LOGE, "Bss Already started...Ignore the request");
1948 EXIT();
1949 return 0;
1950 }
1951
1952 pConfig->persona = pHostapdAdapter->device_mode;
1953
1954 pSapEventCallback = hdd_hostapd_SAPEventCB;
1955 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
1956 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
1957 {
1958 hddLog(LOGE,FL("SAP Start Bss fail\n"));
1959 return -EINVAL;
1960 }
1961
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001962 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07001963 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
1964
1965 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1966
1967 if (!VOS_IS_STATUS_SUCCESS(status))
1968 {
1969 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1970 ("ERROR: HDD vos wait for single_event failed!!\n"));
1971 VOS_ASSERT(0);
1972 }
1973
1974 //Succesfully started Bss update the state bit.
1975 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
1976
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001977#ifdef WLAN_FEATURE_P2P_DEBUG
1978 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
1979 {
1980 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
1981 {
1982 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1983 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001984 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001985 }
1986 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
1987 {
1988 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1989 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001990 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001991 }
1992 }
1993#endif
1994
Jeff Johnson295189b2012-06-20 16:38:30 -07001995 pHostapdState->bCommit = TRUE;
1996 EXIT();
1997
1998 return 0;
1999}
2000
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002001#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002002static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
2003 struct net_device *dev,
2004 struct beacon_parameters *params)
2005{
2006 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2007 int status=VOS_STATUS_SUCCESS;
2008
2009 ENTER();
2010
2011 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
2012
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002013 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2014 {
2015 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2016 "%s:LOGP in Progress. Ignore!!!", __func__);
2017 return -EAGAIN;
2018 }
2019
Jeff Johnson295189b2012-06-20 16:38:30 -07002020 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002021 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002022 )
2023 {
2024 beacon_data_t *old,*new;
2025
2026 old = pAdapter->sessionCtx.ap.beacon;
2027
2028 if (old)
2029 return -EALREADY;
2030
2031 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2032
2033 if(status != VOS_STATUS_SUCCESS)
2034 {
2035 hddLog(VOS_TRACE_LEVEL_FATAL,
2036 "%s:Error!!! Allocating the new beacon\n",__func__);
2037 return -EINVAL;
2038 }
2039
2040 pAdapter->sessionCtx.ap.beacon = new;
2041
2042 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2043 }
2044
2045 EXIT();
2046 return status;
2047}
2048
2049static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
2050 struct net_device *dev,
2051 struct beacon_parameters *params)
2052{
2053 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2054 int status=VOS_STATUS_SUCCESS;
2055
2056 ENTER();
2057
2058 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2059 __func__,pAdapter->device_mode);
2060
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002061 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2062 {
2063 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2064 "%s:LOGP in Progress. Ignore!!!", __func__);
2065 return -EAGAIN;
2066 }
2067
Jeff Johnson295189b2012-06-20 16:38:30 -07002068 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002069 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002070 )
2071 {
2072 beacon_data_t *old,*new;
2073
2074 old = pAdapter->sessionCtx.ap.beacon;
2075
2076 if (!old)
2077 return -ENOENT;
2078
2079 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2080
2081 if(status != VOS_STATUS_SUCCESS) {
2082 hddLog(VOS_TRACE_LEVEL_FATAL,
2083 "%s: Error!!! Allocating the new beacon\n",__func__);
2084 return -EINVAL;
2085 }
2086
2087 pAdapter->sessionCtx.ap.beacon = new;
2088
2089 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2090 }
2091
2092 EXIT();
2093 return status;
2094}
2095
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002096#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
2097
2098#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002099static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
2100 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002101#else
2102static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
2103 struct net_device *dev)
2104#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002105{
2106 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07002107 hdd_context_t *pHddCtx = NULL;
2108 hdd_scaninfo_t *pScanInfo = NULL;
2109 hdd_adapter_t *staAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002110 VOS_STATUS status = 0;
2111
2112 ENTER();
2113
2114 if (NULL == pAdapter)
2115 {
2116 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002117 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002118 return -ENODEV;
2119 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002120
Jeff Johnson4416a782013-03-25 14:17:50 -07002121 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002122 if (NULL == pHddCtx)
2123 {
2124 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002125 "%s: HDD context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002126 return -ENODEV;
2127 }
Jeff Johnson4416a782013-03-25 14:17:50 -07002128 if (pHddCtx->isLogpInProgress)
2129 {
2130 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2131 "%s:LOGP in Progress. Ignore!!!", __func__);
2132 return -EAGAIN;
2133 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002134
2135 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
2136 if (NULL == staAdapter)
2137 {
2138 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
2139 if (NULL == staAdapter)
2140 {
2141 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002142 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002143 return -ENODEV;
2144 }
2145 }
2146
2147 pScanInfo = &pHddCtx->scan_info;
2148
Jeff Johnson4416a782013-03-25 14:17:50 -07002149 if (pHddCtx->isLogpInProgress)
Jeff Johnson295189b2012-06-20 16:38:30 -07002150 {
2151 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2152 return -EAGAIN;
2153 }
2154
2155 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2156
2157 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2158 __func__,pAdapter->device_mode);
2159
Jeff Johnsone7245742012-09-05 17:12:55 -07002160 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
2161 {
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002162 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Jeff Johnsone7245742012-09-05 17:12:55 -07002163 hdd_abort_mac_scan(staAdapter->pHddCtx);
2164 status = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002165 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07002166 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
2167 if (!status)
2168 {
2169 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson902c9832012-12-10 14:28:09 -08002170 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002171 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07002172 VOS_ASSERT(pScanInfo->mScanPending);
2173 return 0;
2174 }
2175 }
2176
Jeff Johnson295189b2012-06-20 16:38:30 -07002177 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002178 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002179 )
2180 {
2181 beacon_data_t *old;
2182
2183 old = pAdapter->sessionCtx.ap.beacon;
2184
2185 if (!old)
2186 return -ENOENT;
2187
Jeff Johnson295189b2012-06-20 16:38:30 -07002188 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002189
2190 mutex_lock(&pHddCtx->sap_lock);
2191 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2192 {
Jeff Johnson4416a782013-03-25 14:17:50 -07002193 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss(pHddCtx->pvosContext) ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07002194 {
2195 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2196
2197 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2198
2199 if (!VOS_IS_STATUS_SUCCESS(status))
2200 {
2201 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2202 ("ERROR: HDD vos wait for single_event failed!!\n"));
2203 VOS_ASSERT(0);
2204 }
2205 }
2206 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2207 }
2208 mutex_unlock(&pHddCtx->sap_lock);
2209
2210 if(status != VOS_STATUS_SUCCESS)
2211 {
2212 hddLog(VOS_TRACE_LEVEL_FATAL,
2213 "%s:Error!!! Stopping the BSS\n",__func__);
2214 return -EINVAL;
2215 }
2216
Jeff Johnson4416a782013-03-25 14:17:50 -07002217 if (ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002218 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
2219 ==eHAL_STATUS_FAILURE)
2220 {
2221 hddLog(LOGE,
2222 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
2223 }
2224
Jeff Johnson4416a782013-03-25 14:17:50 -07002225 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002226 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2227 eANI_BOOLEAN_FALSE) )
2228 {
2229 hddLog(LOGE,
2230 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
2231 }
2232
2233 // Reset WNI_CFG_PROBE_RSP Flags
2234 wlan_hdd_reset_prob_rspies(pAdapter);
2235
2236 pAdapter->sessionCtx.ap.beacon = NULL;
2237 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002238#ifdef WLAN_FEATURE_P2P_DEBUG
2239 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
2240 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
2241 {
2242 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
2243 "GO got removed");
2244 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
2245 }
2246#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002247 }
2248 EXIT();
2249 return status;
2250}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002251
2252#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2253
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302254static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2255 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002256 struct cfg80211_ap_settings *params)
2257{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302258 hdd_adapter_t *pAdapter;
2259 hdd_context_t *pHddCtx;
2260 int status = 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002261
2262 ENTER();
2263
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302264 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002265 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302266 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2267 "%s: Device is Null", __func__);
2268 return -ENODEV;
2269 }
2270
2271 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2272 if (NULL == pAdapter)
2273 {
2274 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2275 "%s: HDD adapter is Null", __func__);
2276 return -ENODEV;
2277 }
2278
2279 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2280 {
2281 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2282 "%s: HDD adapter magic is invalid", __func__);
2283 return -ENODEV;
2284 }
2285
2286 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2287 if (NULL == pHddCtx)
2288 {
2289 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2290 "%s: HDD context is Null", __func__);
2291 return -ENODEV;
2292 }
2293
2294 if (pHddCtx->isLogpInProgress)
2295 {
2296 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2297 "%s: LOGP in Progress. Ignore!!!", __func__);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002298 return -EAGAIN;
2299 }
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302300
2301 if (pHddCtx->isLoadUnloadInProgress)
2302 {
2303 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2304 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
2305 return -EAGAIN;
2306 }
2307
2308 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2309 __func__, pAdapter->device_mode);
2310
2311 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002312 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002313 )
2314 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302315 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002316
2317 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302318
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002319 if (old)
2320 return -EALREADY;
2321
2322 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2323
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302324 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002325 {
2326 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302327 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002328 return -EINVAL;
2329 }
2330 pAdapter->sessionCtx.ap.beacon = new;
Viral Modi3a32cc52013-02-08 11:14:52 -08002331#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2332 wlan_hdd_cfg80211_set_channel(wiphy, dev, params->channel, params->channel_type);
2333#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002334 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2335 params->ssid_len, params->hidden_ssid);
2336 }
2337
2338 EXIT();
2339 return status;
2340}
2341
2342
2343static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
2344 struct net_device *dev,
2345 struct cfg80211_beacon_data *params)
2346{
2347 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2348 int status=VOS_STATUS_SUCCESS;
2349
2350 ENTER();
2351
2352 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2353 __func__, pAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002354 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2355 {
2356 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2357 return -EAGAIN;
2358 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002359
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 {
2364 beacon_data_t *old,*new;
2365
2366 old = pAdapter->sessionCtx.ap.beacon;
2367
2368 if (!old)
2369 return -ENOENT;
2370
2371 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2372
2373 if(status != VOS_STATUS_SUCCESS) {
2374 hddLog(VOS_TRACE_LEVEL_FATAL,
2375 "%s: Error!!! Allocating the new beacon\n",__func__);
2376 return -EINVAL;
2377 }
2378
2379 pAdapter->sessionCtx.ap.beacon = new;
2380
2381 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2382 }
2383
2384 EXIT();
2385 return status;
2386}
2387
2388#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2389
Jeff Johnson295189b2012-06-20 16:38:30 -07002390
2391static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2392 struct net_device *dev,
2393 struct bss_parameters *params)
2394{
2395 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2396
2397 ENTER();
2398
2399 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2400 __func__,pAdapter->device_mode);
2401
2402 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002403 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002404 )
2405 {
2406 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2407 * want to update this parameter */
2408 if (-1 != params->ap_isolate)
2409 {
2410 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
2411 }
2412 }
2413
2414 EXIT();
2415 return 0;
2416}
2417
2418/*
2419 * FUNCTION: wlan_hdd_cfg80211_change_iface
2420 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2421 */
2422int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2423 struct net_device *ndev,
2424 enum nl80211_iftype type,
2425 u32 *flags,
2426 struct vif_params *params
2427 )
2428{
2429 struct wireless_dev *wdev;
2430 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2431 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002432 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002433 tCsrRoamProfile *pRoamProfile = NULL;
2434 eCsrRoamBssType LastBSSType;
2435 hdd_config_t *pConfig = pHddCtx->cfg_ini;
2436 eMib_dot11DesiredBssType connectedBssType;
2437 VOS_STATUS status;
2438
2439 ENTER();
2440
2441 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2442 {
2443 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2444 return -EAGAIN;
2445 }
2446
2447 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2448 __func__, pAdapter->device_mode);
2449
2450 wdev = ndev->ieee80211_ptr;
2451
2452#ifdef WLAN_BTAMP_FEATURE
2453 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2454 (NL80211_IFTYPE_ADHOC == type)||
2455 (NL80211_IFTYPE_AP == type)||
2456 (NL80211_IFTYPE_P2P_GO == type))
2457 {
2458 pHddCtx->isAmpAllowed = VOS_FALSE;
2459 // stop AMP traffic
2460 status = WLANBAP_StopAmp();
2461 if(VOS_STATUS_SUCCESS != status )
2462 {
2463 pHddCtx->isAmpAllowed = VOS_TRUE;
2464 hddLog(VOS_TRACE_LEVEL_FATAL,
2465 "%s: Failed to stop AMP", __func__);
2466 return -EINVAL;
2467 }
2468 }
2469#endif //WLAN_BTAMP_FEATURE
2470 /* Reset the current device mode bit mask*/
2471 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2472
2473 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07002474 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002475 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002476 )
2477 {
2478 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2479 pRoamProfile = &pWextState->roamProfile;
2480 LastBSSType = pRoamProfile->BSSType;
2481
2482 switch (type)
2483 {
2484 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002485 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002486 hddLog(VOS_TRACE_LEVEL_INFO,
2487 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2488 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002489#ifdef WLAN_FEATURE_11AC
2490 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2491 {
2492 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2493 }
2494#endif
2495 pRoamProfile->phyMode =
2496 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002497 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002498 //Check for sub-string p2p to confirm its a p2p interface
2499 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002500 {
2501 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2502 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2503 }
2504 else
2505 {
2506 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002507 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002508 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002509 break;
2510 case NL80211_IFTYPE_ADHOC:
2511 hddLog(VOS_TRACE_LEVEL_INFO,
2512 "%s: setting interface Type to ADHOC", __func__);
2513 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2514 pRoamProfile->phyMode =
2515 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
2516 wdev->iftype = type;
2517 break;
2518
2519 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002520 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002521 {
2522 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2523 "%s: setting interface Type to %s", __func__,
2524 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2525
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002526 //Cancel any remain on channel for GO mode
2527 if (NL80211_IFTYPE_P2P_GO == type)
2528 {
2529 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2530 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002531 if (NL80211_IFTYPE_AP == type)
2532 {
2533 /* As Loading WLAN Driver one interface being created for p2p device
2534 * address. This will take one HW STA and the max number of clients
2535 * that can connect to softAP will be reduced by one. so while changing
2536 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2537 * interface as it is not required in SoftAP mode.
2538 */
2539
2540 // Get P2P Adapter
2541 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2542
2543 if (pP2pAdapter)
2544 {
2545 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2546 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2547 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2548 }
2549 }
2550
Jeff Johnson295189b2012-06-20 16:38:30 -07002551 //De-init the adapter.
2552 hdd_stop_adapter( pHddCtx, pAdapter );
2553 hdd_deinit_adapter( pHddCtx, pAdapter );
2554 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
Jeff Johnson295189b2012-06-20 16:38:30 -07002555 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2556 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002557
2558 //Disable BMPS and IMPS if enabled
2559 //before starting Go
2560 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2561 {
2562 if(VOS_STATUS_E_FAILURE ==
2563 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2564 {
2565 //Fail to Exit BMPS
2566 VOS_ASSERT(0);
2567 }
2568 }
2569
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002570 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2571 (pConfig->apRandomBssidEnabled))
2572 {
2573 /* To meet Android requirements create a randomized
2574 MAC address of the form 02:1A:11:Fx:xx:xx */
2575 get_random_bytes(&ndev->dev_addr[3], 3);
2576 ndev->dev_addr[0] = 0x02;
2577 ndev->dev_addr[1] = 0x1A;
2578 ndev->dev_addr[2] = 0x11;
2579 ndev->dev_addr[3] |= 0xF0;
2580 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2581 VOS_MAC_ADDR_SIZE);
2582 pr_info("wlan: Generated HotSpot BSSID "
2583 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2584 ndev->dev_addr[0],
2585 ndev->dev_addr[1],
2586 ndev->dev_addr[2],
2587 ndev->dev_addr[3],
2588 ndev->dev_addr[4],
2589 ndev->dev_addr[5]);
2590 }
2591
Jeff Johnson295189b2012-06-20 16:38:30 -07002592 hdd_set_ap_ops( pAdapter->dev );
2593
2594 status = hdd_init_ap_mode(pAdapter);
2595 if(status != VOS_STATUS_SUCCESS)
2596 {
2597 hddLog(VOS_TRACE_LEVEL_FATAL,
2598 "%s: Error initializing the ap mode", __func__);
2599 return -EINVAL;
2600 }
2601 hdd_set_conparam(1);
2602
Jeff Johnson295189b2012-06-20 16:38:30 -07002603 /*interface type changed update in wiphy structure*/
2604 if(wdev)
2605 {
2606 wdev->iftype = type;
2607 pHddCtx->change_iface = type;
2608 }
2609 else
2610 {
2611 hddLog(VOS_TRACE_LEVEL_ERROR,
2612 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2613 return -EINVAL;
2614 }
2615 goto done;
2616 }
2617
2618 default:
2619 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2620 __func__);
2621 return -EOPNOTSUPP;
2622 }
2623 }
2624 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002625 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002626 )
2627 {
2628 switch(type)
2629 {
2630 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002631 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002632 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002633 hdd_stop_adapter( pHddCtx, pAdapter );
2634 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002635 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002636 //Check for sub-string p2p to confirm its a p2p interface
2637 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002638 {
2639 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2640 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2641 }
2642 else
2643 {
2644 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002645 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002646 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002647 hdd_set_conparam(0);
2648 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002649 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2650 hdd_set_station_ops( pAdapter->dev );
2651 status = hdd_init_station_mode( pAdapter );
2652 if( VOS_STATUS_SUCCESS != status )
2653 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002654 /* In case of JB, for P2P-GO, only change interface will be called,
2655 * This is the right place to enable back bmps_imps()
2656 */
2657 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002658 goto done;
2659 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002660 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002661 wdev->iftype = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002662 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2663 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07002664 goto done;
2665 default:
2666 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2667 __func__);
2668 return -EOPNOTSUPP;
2669
2670 }
2671
2672 }
2673 else
2674 {
2675 return -EOPNOTSUPP;
2676 }
2677
2678
2679 if(pRoamProfile)
2680 {
2681 if ( LastBSSType != pRoamProfile->BSSType )
2682 {
2683 /*interface type changed update in wiphy structure*/
2684 wdev->iftype = type;
2685
2686 /*the BSS mode changed, We need to issue disconnect
2687 if connected or in IBSS disconnect state*/
2688 if ( hdd_connGetConnectedBssType(
2689 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2690 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2691 {
2692 /*need to issue a disconnect to CSR.*/
2693 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2694 if( eHAL_STATUS_SUCCESS ==
2695 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2696 pAdapter->sessionId,
2697 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2698 {
2699 wait_for_completion_interruptible_timeout(
2700 &pAdapter->disconnect_comp_var,
2701 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2702 }
2703 }
2704 }
2705 }
2706
2707done:
2708 /*set bitmask based on updated value*/
2709 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
2710#ifdef WLAN_BTAMP_FEATURE
2711 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
2712 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2713 {
2714 //we are ok to do AMP
2715 pHddCtx->isAmpAllowed = VOS_TRUE;
2716 }
2717#endif //WLAN_BTAMP_FEATURE
2718 EXIT();
2719 return 0;
2720}
2721
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002722#ifdef FEATURE_WLAN_TDLS
2723static int wlan_hdd_tdls_add_station(struct wiphy *wiphy,
2724 struct net_device *dev, u8 *mac, bool update, tCsrStaParams *StaParams)
2725{
2726 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2727 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2728 VOS_STATUS status;
2729
2730 ENTER();
2731
2732 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
2733 {
2734 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2735 "Invalid arguments");
2736 return -EINVAL;
2737 }
Hoonki Lee27511902013-03-14 18:19:06 -07002738
2739 if ((eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) ||
2740 (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode))
2741 {
2742 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2743 "%s: TDLS mode is disabled OR not enabled in FW."
2744 MAC_ADDRESS_STR " Request declined.",
2745 __func__, MAC_ADDR_ARRAY(mac));
2746 return -ENOTSUPP;
2747 }
2748
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002749 if (pHddCtx->isLogpInProgress)
2750 {
2751 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2752 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07002753 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002754 return -EBUSY;
2755 }
2756
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002757 /* when self is on-going, we dont' want to change link_status */
2758 if ((0 == update) && wlan_hdd_tdls_is_peer_progress(pAdapter, mac))
2759 {
2760 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2761 "%s: " MAC_ADDRESS_STR
2762 " TDLS setup is ongoing. Request declined.",
2763 __func__, MAC_ADDR_ARRAY(mac));
2764 return -EPERM;
2765 }
2766
2767 /* when others are on-going, we want to change link_status to idle */
2768 if (wlan_hdd_tdls_is_progress(pAdapter, mac, TRUE))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002769 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002770 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2771 "%s: " MAC_ADDRESS_STR
2772 " TDLS setup is ongoing. Request declined.",
2773 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002774 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002775 }
2776
2777 /* first to check if we reached to maximum supported TDLS peer.
2778 TODO: for now, return -EPERM looks working fine,
2779 but need to check if any other errno fit into this category.*/
2780 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
2781 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002782 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2783 "%s: " MAC_ADDRESS_STR
2784 " TDLS Max peer already connected. Request declined.",
2785 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002786 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002787 }
2788 else
2789 {
2790 hddTdlsPeer_t *pTdlsPeer;
2791 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac);
2792 if (pTdlsPeer && (eTDLS_LINK_CONNECTED == pTdlsPeer->link_status))
2793 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002794 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2795 "%s: " MAC_ADDRESS_STR " already connected. Request declined.",
2796 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002797 return -EPERM;
2798 }
2799 }
2800
2801 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_CONNECTING);
2802
2803 INIT_COMPLETION(pAdapter->tdls_add_station_comp);
2804
2805 if (!update)
2806 {
2807 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
2808 pAdapter->sessionId, mac);
2809 }
2810 else
2811 {
2812 status = sme_ChangeTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
2813 pAdapter->sessionId, mac, StaParams);
2814 }
2815
2816 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_add_station_comp,
2817 msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
2818
2819 if (!status)
2820 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002821 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002822 "%s: timeout waiting for tdls add station indication",
2823 __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002824 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002825 }
2826 if ( eHAL_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus)
2827 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002828 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002829 "%s: Add Station is unsucessful", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002830 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002831 }
2832
2833 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07002834
2835error:
2836 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
2837 return -EPERM;
2838
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002839}
2840#endif
2841
Jeff Johnson295189b2012-06-20 16:38:30 -07002842static int wlan_hdd_change_station(struct wiphy *wiphy,
2843 struct net_device *dev,
2844 u8 *mac,
2845 struct station_parameters *params)
2846{
2847 VOS_STATUS status = VOS_STATUS_SUCCESS;
2848 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2849 v_MACADDR_t STAMacAddress;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002850#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002851 tCsrStaParams StaParams = {0};
2852 u32 set;
2853 tANI_U8 isBufSta = 0;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002854#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07002855 ENTER();
2856
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002857 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2858 {
2859 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2860 "%s:LOGP in Progress. Ignore!!!", __func__);
2861 return -EAGAIN;
2862 }
2863
Jeff Johnson295189b2012-06-20 16:38:30 -07002864 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
2865
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002866#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002867 StaParams.capability = params->capability;
2868 StaParams.uapsd_queues = params->uapsd_queues;
2869 StaParams.max_sp = params->max_sp;
2870
2871 if (0 != params->ext_capab_len)
2872 vos_mem_copy(StaParams.extn_capability, params->ext_capab,
2873 sizeof(StaParams.extn_capability));
2874
2875 if (NULL != params->ht_capa)
2876 vos_mem_copy(&StaParams.HTCap, params->ht_capa, sizeof(tSirHTCap));
2877
2878 StaParams.supported_rates_len = params->supported_rates_len;
2879
2880 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
2881 * The supported_rates array , for all the structures propogating till Add Sta
2882 * to the firmware has to be modified , if the supplicant (ieee80211) is
2883 * modified to send more rates.
2884 */
2885
2886 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
2887 */
2888 if (StaParams.supported_rates_len > SIR_MAC_MAX_SUPP_RATES)
2889 StaParams.supported_rates_len = SIR_MAC_MAX_SUPP_RATES;
2890
2891 if (0 != StaParams.supported_rates_len) {
2892 int i = 0;
2893 vos_mem_copy(StaParams.supported_rates, params->supported_rates,
2894 StaParams.supported_rates_len);
2895 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2896 "Supported Rates with Length %d", StaParams.supported_rates_len);
2897 for (i=0; i < StaParams.supported_rates_len; i++)
2898 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2899 "[%d]: %0x", i, StaParams.supported_rates[i]);
2900 }
2901
2902 if (NULL != params->vht_capa)
2903 vos_mem_copy(&StaParams.VHTCap, params->vht_capa, sizeof(tSirVHTCap));
2904
2905 set = params->sta_flags_set;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002906#endif
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002907
2908 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2909 || (pAdapter->device_mode == WLAN_HDD_P2P_GO))
Jeff Johnson295189b2012-06-20 16:38:30 -07002910 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002911 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
Jeff Johnson295189b2012-06-20 16:38:30 -07002912 {
2913 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
2914 WLANTL_STA_AUTHENTICATED);
2915
2916 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002917 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002918 return -EINVAL;
2919 }
2920 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002921#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002922 else if (pAdapter->device_mode == WLAN_HDD_INFRA_STATION ) {
2923 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
2924 if (0 != params->ext_capab_len ) {
2925 /*Define A Macro : TODO Sunil*/
2926 if ((1<<4) & StaParams.extn_capability[3]) {
2927 isBufSta = 1;
2928 }
2929 }
2930 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2931 "%s: TDLS Peer Parameters.", __func__);
2932 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2933 "uapsd_queues: %0x\n", params->uapsd_queues);
2934 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2935 "max_sp: %0x\n", params->max_sp);
2936 if (params->ht_capa) {
2937 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2938 "ht_capa->cap_info: %0x\n", params->ht_capa->cap_info);
2939 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2940 "ht_capa->ampdu_params_info: %0x\n",
2941 params->ht_capa->ampdu_params_info);
2942 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2943 "ht_capa->extended_capabilities: %0x\n",
2944 params->ht_capa->extended_ht_cap_info);
2945 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2946 "ht_capa->tx_BF_cap_info: %0x\n",
2947 params->ht_capa->tx_BF_cap_info);
2948 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2949 "ht_capa->antenna_selection_info: %0x\n",
2950 params->ht_capa->antenna_selection_info);
2951 }
2952 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2953 "params->capability: %0x\n",params->capability);
2954 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2955 "params->ext_capab_len: %0x\n",params->ext_capab_len);
2956 if (0 != params->ext_capab_len )
2957 {
2958 int i =0;
2959 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2960 "Extended capabilities:");
2961 for (i=0; i < params->ext_capab_len; i++)
2962 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2963 "[%d]: %0x", i, params->ext_capab[i]);
2964 }
2965 //status = wlan_hdd_tdls_set_peer_caps( mac, params->uapsd_queues,
2966 // params->max_sp, isBufSta);
2967 if (VOS_STATUS_SUCCESS != status) {
2968 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2969 "%s: wlan_hdd_tdls_set_peer_caps failed!", __func__);
2970 return -EINVAL;
2971 }
2972 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2973 "ht_capa->cap_info: %0x\n", StaParams.HTCap.capInfo);
2974 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 1, &StaParams);
2975
2976 if (VOS_STATUS_SUCCESS != status) {
2977 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2978 "%s: sme_ChangeTdlsPeerSta failed!", __func__);
2979 return -EINVAL;
2980 }
2981 }
2982 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002983#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002984
Jeff Johnsone7245742012-09-05 17:12:55 -07002985 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002986 return status;
2987}
2988
2989/*
2990 * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
2991 * This function is used to get peer station index in IBSS mode
2992 */
2993static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
2994{
2995 u8 idx = 0;
2996 u8 temp[VOS_MAC_ADDR_SIZE] = {0};
2997 ENTER();
2998 memset(temp, 0, VOS_MAC_ADDR_SIZE);
2999 for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
3000 {
3001 if ( (0 !=
3002 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
3003 && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
3004 temp, VOS_MAC_ADDR_SIZE)
3005 )
3006 {
3007 return idx;
3008 }
3009 }
3010 return idx;
3011}
3012
3013
3014/*
3015 * FUNCTION: wlan_hdd_cfg80211_add_key
3016 * This function is used to initialize the key information
3017 */
3018#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003019static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003020 struct net_device *ndev,
3021 u8 key_index, bool pairwise,
3022 const u8 *mac_addr,
3023 struct key_params *params
3024 )
3025#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003026static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003027 struct net_device *ndev,
3028 u8 key_index, const u8 *mac_addr,
3029 struct key_params *params
3030 )
3031#endif
3032{
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003033 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003034 tCsrRoamSetKey setKey;
3035 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3036 int status = 0;
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003037 v_U32_t roamId= 0xFF;
3038 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003039 hdd_hostapd_state_t *pHostapdState;
3040 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003041 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07003042
3043 ENTER();
3044
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003045 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3046 {
3047 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3048 "%s:LOGP in Progress. Ignore!!!", __func__);
3049 return -EAGAIN;
3050 }
3051
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003052 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
3053 __func__, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003054
3055 if (CSR_MAX_NUM_KEY <= key_index)
3056 {
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003057 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003058 key_index);
3059
3060 return -EINVAL;
3061 }
3062
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003063 if (CSR_MAX_KEY_LEN < params->key_len)
3064 {
3065 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key length %d", __func__,
3066 params->key_len);
3067
3068 return -EINVAL;
3069 }
3070
3071 hddLog(VOS_TRACE_LEVEL_INFO,
3072 "%s: called with key index = %d & key length %d",
3073 __func__, key_index, params->key_len);
Jeff Johnson295189b2012-06-20 16:38:30 -07003074
3075 /*extract key idx, key len and key*/
3076 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3077 setKey.keyId = key_index;
3078 setKey.keyLength = params->key_len;
3079 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
3080
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003081 switch (params->cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07003082 {
3083 case WLAN_CIPHER_SUITE_WEP40:
3084 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
3085 break;
3086
3087 case WLAN_CIPHER_SUITE_WEP104:
3088 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
3089 break;
3090
3091 case WLAN_CIPHER_SUITE_TKIP:
3092 {
3093 u8 *pKey = &setKey.Key[0];
3094 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
3095
3096 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
3097
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003098 /*Supplicant sends the 32bytes key in this order
Jeff Johnson295189b2012-06-20 16:38:30 -07003099
3100 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003101 | Tk1 |TX-MIC | RX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003102 |--------------|----------|----------|
3103 <---16bytes---><--8bytes--><--8bytes-->
3104
3105 */
3106 /*Sme expects the 32 bytes key to be in the below order
3107
3108 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003109 | Tk1 |RX-MIC | TX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003110 |--------------|----------|----------|
3111 <---16bytes---><--8bytes--><--8bytes-->
3112 */
3113 /* Copy the Temporal Key 1 (TK1) */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003114 vos_mem_copy(pKey, params->key, 16);
Jeff Johnson295189b2012-06-20 16:38:30 -07003115
3116 /*Copy the rx mic first*/
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003117 vos_mem_copy(&pKey[16], &params->key[24], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003118
3119 /*Copy the tx mic */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003120 vos_mem_copy(&pKey[24], &params->key[16], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003121
3122
3123 break;
3124 }
3125
3126 case WLAN_CIPHER_SUITE_CCMP:
3127 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
3128 break;
3129
3130#ifdef FEATURE_WLAN_WAPI
3131 case WLAN_CIPHER_SUITE_SMS4:
3132 {
3133 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3134 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
3135 params->key, params->key_len);
3136 return 0;
3137 }
3138#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003139
Jeff Johnson295189b2012-06-20 16:38:30 -07003140#ifdef FEATURE_WLAN_CCX
3141 case WLAN_CIPHER_SUITE_KRK:
3142 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
3143 break;
3144#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003145
3146#ifdef WLAN_FEATURE_11W
3147 case WLAN_CIPHER_SUITE_AES_CMAC:
3148 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
3149 /* Temporarily we will ignore the setting of the IGTK. Once the Riva
3150 firmware is modified to handle the IGTK, then we will proceeed normally.
3151 For now, we just return success. */
3152 return 0;
3153 /* break; */
3154#endif
3155
Jeff Johnson295189b2012-06-20 16:38:30 -07003156 default:
3157 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
3158 __func__, params->cipher);
3159 return -EOPNOTSUPP;
3160 }
3161
3162 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
3163 __func__, setKey.encType);
3164
3165
3166
3167 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003168 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07003169 )
3170 {
3171
3172
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003173 if (
Jeff Johnson295189b2012-06-20 16:38:30 -07003174#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3175 (!pairwise)
3176#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003177 (!mac_addr || is_broadcast_ether_addr(mac_addr))
Jeff Johnson295189b2012-06-20 16:38:30 -07003178#endif
3179 )
3180 {
3181 /* set group key*/
3182 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson1250df42012-12-10 14:31:52 -08003183 "%s- %d: setting Broadcast key",
Jeff Johnson295189b2012-06-20 16:38:30 -07003184 __func__, __LINE__);
3185 setKey.keyDirection = eSIR_RX_ONLY;
3186 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3187 }
3188 else
3189 {
3190 /* set pairwise key*/
3191 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3192 "%s- %d: setting pairwise key",
3193 __func__, __LINE__);
3194 setKey.keyDirection = eSIR_TX_RX;
3195 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3196 }
3197
3198 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003199 if( pHostapdState->bssState == BSS_START )
3200 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003201 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3202
3203 if ( status != eHAL_STATUS_SUCCESS )
3204 {
3205 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3206 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3207 __LINE__, status );
3208 }
3209 }
3210
3211 /* Saving WEP keys */
3212 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
3213 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
3214 {
3215 //Save the wep key in ap context. Issue setkey after the BSS is started.
3216 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3217 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
3218 }
3219 else
3220 {
3221 //Save the key in ap context. Issue setkey after the BSS is started.
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003222 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003223 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
3224 }
3225 }
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003226 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
3227 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) )
Jeff Johnson295189b2012-06-20 16:38:30 -07003228 {
3229 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3230 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3231
3232 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
3233
Venkata Prathyusha Kuntupalliee2ce712013-01-17 14:09:24 -08003234 pWextState->roamProfile.Keys.defaultIndex = key_index;
3235
3236
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003237 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07003238 params->key, params->key_len);
3239
3240 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3241
3242 if (!( ( IW_AUTH_KEY_MGMT_802_1X
3243 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
3244 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3245 )
3246 &&
3247 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3248 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3249 )
3250 )
3251 {
3252 /* in case of static WEP, macaddr/bssid is not coming from nl80211
3253 * interface, copy bssid for pairwise key and group macaddr for
3254 * group key initialization*/
3255
3256 tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
3257
3258 pWextState->roamProfile.negotiatedUCEncryptionType =
3259 pHddStaCtx->conn_info.ucEncryptionType =
3260 ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
3261 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
3262 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
3263
3264
3265 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3266 "%s: Negotiated encryption type %d", __func__,
3267 pWextState->roamProfile.negotiatedUCEncryptionType);
3268
3269 sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
3270 &pWextState->roamProfile, true);
3271 setKey.keyLength = 0;
3272 setKey.keyDirection = eSIR_TX_RX;
3273
3274#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3275 if (pairwise)
3276 {
3277#endif
3278 if (mac_addr)
3279 {
3280 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3281 }
3282 else
3283 {
3284 /* macaddr is NULL, set the peerMac to bssId in case of BSS,
3285 * and peerMacAddress in case of IBSS*/
3286 if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
3287 {
3288 u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
3289 if (HDD_MAX_NUM_IBSS_STA != staidx)
3290 {
3291 vos_mem_copy(setKey.peerMac,
3292 &pHddStaCtx->conn_info.peerMacAddress[staidx],
3293 WNI_CFG_BSSID_LEN);
3294
3295 }
3296 else
3297 {
3298 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
3299 __func__);
3300 return -EOPNOTSUPP;
3301 }
3302 }
3303 else
3304 {
3305 vos_mem_copy(setKey.peerMac,
3306 &pHddStaCtx->conn_info.bssId[0],
3307 WNI_CFG_BSSID_LEN);
3308 }
3309 }
3310#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3311 }
3312 else
3313 {
3314 /* set group key*/
3315 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3316 "%s- %d: setting Group key",
3317 __func__, __LINE__);
3318 setKey.keyDirection = eSIR_RX_ONLY;
3319 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3320 }
3321#endif
3322 }
3323 else if (
3324#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3325 (!pairwise)
3326#else
3327 (!mac_addr || is_broadcast_ether_addr(mac_addr))
3328#endif
3329 )
3330 {
3331 /* set group key*/
3332 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3333 "%s- %d: setting Group key",
3334 __func__, __LINE__);
3335 setKey.keyDirection = eSIR_RX_ONLY;
3336 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3337 }
3338 else
3339 {
3340 /* set pairwise key*/
3341 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3342 "%s- %d: setting pairwise key",
3343 __func__, __LINE__);
3344 setKey.keyDirection = eSIR_TX_RX;
3345 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3346 }
3347
3348 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3349 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3350 __func__, setKey.peerMac[0], setKey.peerMac[1],
3351 setKey.peerMac[2], setKey.peerMac[3],
3352 setKey.peerMac[4], setKey.peerMac[5],
3353 setKey.keyDirection);
3354
3355 vos_status = wlan_hdd_check_ula_done(pAdapter);
3356
3357 if ( vos_status != VOS_STATUS_SUCCESS )
3358 {
3359 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3360 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
3361 __LINE__, vos_status );
3362
3363 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3364
3365 return -EINVAL;
3366
3367 }
3368
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003369#ifdef WLAN_FEATURE_VOWIFI_11R
3370 /* The supplicant may attempt to set the PTK once pre-authentication is done.
3371 Save the key in the UMAC and include it in the ADD BSS request */
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003372 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303373 if( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_WAIT )
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003374 {
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303375 return -EINVAL;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003376 }
3377#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07003378
3379 /* issue set key request to SME*/
3380 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3381 pAdapter->sessionId, &setKey, &roamId );
3382
3383 if ( 0 != status )
3384 {
3385 hddLog(VOS_TRACE_LEVEL_ERROR,
3386 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3387 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3388 return -EINVAL;
3389 }
3390
3391
3392 /* in case of IBSS as there was no information available about WEP keys during
3393 * IBSS join, group key intialized with NULL key, so re-initialize group key
3394 * with correct value*/
3395 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
3396 !( ( IW_AUTH_KEY_MGMT_802_1X
3397 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
3398 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3399 )
3400 &&
3401 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3402 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3403 )
3404 )
3405 {
3406 setKey.keyDirection = eSIR_RX_ONLY;
3407 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3408
3409 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3410 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3411 __func__, setKey.peerMac[0], setKey.peerMac[1],
3412 setKey.peerMac[2], setKey.peerMac[3],
3413 setKey.peerMac[4], setKey.peerMac[5],
3414 setKey.keyDirection);
3415
3416 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3417 pAdapter->sessionId, &setKey, &roamId );
3418
3419 if ( 0 != status )
3420 {
3421 hddLog(VOS_TRACE_LEVEL_ERROR,
3422 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
3423 __func__, status);
3424 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3425 return -EINVAL;
3426 }
3427 }
3428 }
3429
3430 return 0;
3431}
3432
3433/*
3434 * FUNCTION: wlan_hdd_cfg80211_get_key
3435 * This function is used to get the key information
3436 */
3437#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3438static int wlan_hdd_cfg80211_get_key(
3439 struct wiphy *wiphy,
3440 struct net_device *ndev,
3441 u8 key_index, bool pairwise,
3442 const u8 *mac_addr, void *cookie,
3443 void (*callback)(void *cookie, struct key_params*)
3444 )
3445#else
3446static int wlan_hdd_cfg80211_get_key(
3447 struct wiphy *wiphy,
3448 struct net_device *ndev,
3449 u8 key_index, const u8 *mac_addr, void *cookie,
3450 void (*callback)(void *cookie, struct key_params*)
3451 )
3452#endif
3453{
3454 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3455 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3456 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
3457 struct key_params params;
3458
3459 ENTER();
3460
3461 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3462 __func__,pAdapter->device_mode);
3463
3464 memset(&params, 0, sizeof(params));
3465
3466 if (CSR_MAX_NUM_KEY <= key_index)
3467 {
3468 return -EINVAL;
3469 }
3470
3471 switch(pRoamProfile->EncryptionType.encryptionType[0])
3472 {
3473 case eCSR_ENCRYPT_TYPE_NONE:
3474 params.cipher = IW_AUTH_CIPHER_NONE;
3475 break;
3476
3477 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3478 case eCSR_ENCRYPT_TYPE_WEP40:
3479 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3480 break;
3481
3482 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3483 case eCSR_ENCRYPT_TYPE_WEP104:
3484 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3485 break;
3486
3487 case eCSR_ENCRYPT_TYPE_TKIP:
3488 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3489 break;
3490
3491 case eCSR_ENCRYPT_TYPE_AES:
3492 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3493 break;
3494
3495 default:
3496 params.cipher = IW_AUTH_CIPHER_NONE;
3497 break;
3498 }
3499
3500 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3501 params.seq_len = 0;
3502 params.seq = NULL;
3503 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3504 callback(cookie, &params);
3505 return 0;
3506}
3507
3508/*
3509 * FUNCTION: wlan_hdd_cfg80211_del_key
3510 * This function is used to delete the key information
3511 */
3512#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3513static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3514 struct net_device *ndev,
3515 u8 key_index,
3516 bool pairwise,
3517 const u8 *mac_addr
3518 )
3519#else
3520static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3521 struct net_device *ndev,
3522 u8 key_index,
3523 const u8 *mac_addr
3524 )
3525#endif
3526{
3527 int status = 0;
3528
3529 //This code needs to be revisited. There is sme_removeKey API, we should
3530 //plan to use that. After the change to use correct index in setkey,
3531 //it is observed that this is invalidating peer
3532 //key index whenever re-key is done. This is affecting data link.
3533 //It should be ok to ignore del_key.
3534#if 0
3535 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3536 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
3537 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3538 tCsrRoamSetKey setKey;
3539 v_U32_t roamId= 0xFF;
3540
3541 ENTER();
3542
3543 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3544 __func__,pAdapter->device_mode);
3545
3546 if (CSR_MAX_NUM_KEY <= key_index)
3547 {
3548 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3549 key_index);
3550
3551 return -EINVAL;
3552 }
3553
3554 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3555 setKey.keyId = key_index;
3556
3557 if (mac_addr)
3558 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3559 else
3560 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3561
3562 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3563
3564 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003565 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07003566 )
3567 {
3568
3569 hdd_hostapd_state_t *pHostapdState =
3570 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3571 if( pHostapdState->bssState == BSS_START)
3572 {
3573 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3574
3575 if ( status != eHAL_STATUS_SUCCESS )
3576 {
3577 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3578 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3579 __LINE__, status );
3580 }
3581 }
3582 }
3583 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003584 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003585 )
3586 {
3587 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3588
3589 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3590
3591 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3592 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
3593 __func__, setKey.peerMac[0], setKey.peerMac[1],
3594 setKey.peerMac[2], setKey.peerMac[3],
3595 setKey.peerMac[4], setKey.peerMac[5]);
3596 if(pAdapter->sessionCtx.station.conn_info.connState ==
3597 eConnectionState_Associated)
3598 {
3599 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3600 pAdapter->sessionId, &setKey, &roamId );
3601
3602 if ( 0 != status )
3603 {
3604 hddLog(VOS_TRACE_LEVEL_ERROR,
3605 "%s: sme_RoamSetKey failure, returned %d",
3606 __func__, status);
3607 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3608 return -EINVAL;
3609 }
3610 }
3611 }
3612#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003613 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003614 return status;
3615}
3616
3617/*
3618 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3619 * This function is used to set the default tx key index
3620 */
3621#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3622static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3623 struct net_device *ndev,
3624 u8 key_index,
3625 bool unicast, bool multicast)
3626#else
3627static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3628 struct net_device *ndev,
3629 u8 key_index)
3630#endif
3631{
3632 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3633 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3634 int status = 0;
3635 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3636
3637 ENTER();
3638
3639 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3640 __func__,pAdapter->device_mode, key_index);
3641
3642 if (CSR_MAX_NUM_KEY <= key_index)
3643 {
3644 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3645 key_index);
3646
3647 return -EINVAL;
3648 }
3649
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003650 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3651 {
3652 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3653 "%s:LOGP in Progress. Ignore!!!", __func__);
3654 return -EAGAIN;
3655 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003656
3657 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003658 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003659 )
3660 {
3661 if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
3662 (eCSR_ENCRYPT_TYPE_TKIP !=
3663 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3664 (eCSR_ENCRYPT_TYPE_AES !=
3665 pWextState->roamProfile.EncryptionType.encryptionType[0])
3666 )
3667 {
3668 /* if default key index is not same as previous one,
3669 * then update the default key index */
3670
3671 tCsrRoamSetKey setKey;
3672 v_U32_t roamId= 0xFF;
3673 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
3674
3675 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
3676 __func__, key_index);
3677
3678 Keys->defaultIndex = (u8)key_index;
3679 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3680 setKey.keyId = key_index;
3681 setKey.keyLength = Keys->KeyLength[key_index];
3682
3683 vos_mem_copy(&setKey.Key[0],
3684 &Keys->KeyMaterial[key_index][0],
3685 Keys->KeyLength[key_index]);
3686
3687 setKey.keyDirection = eSIR_TX_ONLY;
3688
3689 vos_mem_copy(setKey.peerMac,
3690 &pHddStaCtx->conn_info.bssId[0],
3691 WNI_CFG_BSSID_LEN);
3692
3693 setKey.encType =
3694 pWextState->roamProfile.EncryptionType.encryptionType[0];
3695
3696 /* issue set key request */
3697 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3698 pAdapter->sessionId, &setKey, &roamId );
3699
3700 if ( 0 != status )
3701 {
3702 hddLog(VOS_TRACE_LEVEL_ERROR,
3703 "%s: sme_RoamSetKey failed, returned %d", __func__,
3704 status);
3705 return -EINVAL;
3706 }
3707 }
3708 }
3709
3710 /* In SoftAp mode setting key direction for default mode */
3711 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3712 {
3713 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3714 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3715 (eCSR_ENCRYPT_TYPE_AES !=
3716 pWextState->roamProfile.EncryptionType.encryptionType[0])
3717 )
3718 {
3719 /* Saving key direction for default key index to TX default */
3720 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3721 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3722 }
3723 }
3724
3725 return status;
3726}
3727
Jeff Johnson295189b2012-06-20 16:38:30 -07003728/*
3729 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3730 * This function is used to inform the BSS details to nl80211 interface.
3731 */
3732static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3733 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3734{
3735 struct net_device *dev = pAdapter->dev;
3736 struct wireless_dev *wdev = dev->ieee80211_ptr;
3737 struct wiphy *wiphy = wdev->wiphy;
3738 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3739 int chan_no;
3740 int ie_length;
3741 const char *ie;
3742 unsigned int freq;
3743 struct ieee80211_channel *chan;
3744 int rssi = 0;
3745 struct cfg80211_bss *bss = NULL;
3746
3747 ENTER();
3748
3749 if( NULL == pBssDesc )
3750 {
3751 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3752 return bss;
3753 }
3754
3755 chan_no = pBssDesc->channelId;
3756 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3757 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3758
3759 if( NULL == ie )
3760 {
3761 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3762 return bss;
3763 }
3764
3765#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3766 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3767 {
3768 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3769 }
3770 else
3771 {
3772 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3773 }
3774#else
3775 freq = ieee80211_channel_to_frequency(chan_no);
3776#endif
3777
3778 chan = __ieee80211_get_channel(wiphy, freq);
3779
3780 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3781 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3782 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3783 if (bss == NULL)
3784 {
3785 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3786
3787 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3788 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3789 pBssDesc->capabilityInfo,
3790 pBssDesc->beaconInterval, ie, ie_length,
3791 rssi, GFP_KERNEL ));
3792}
3793 else
3794 {
3795 return bss;
3796 }
3797}
3798
3799
3800
3801/*
3802 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3803 * This function is used to inform the BSS details to nl80211 interface.
3804 */
3805struct cfg80211_bss*
3806wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3807 tSirBssDescription *bss_desc
3808 )
3809{
3810 /*
3811 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3812 already exists in bss data base of cfg80211 for that particular BSS ID.
3813 Using cfg80211_inform_bss_frame to update the bss entry instead of
3814 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3815 now there is no possibility to get the mgmt(probe response) frame from PE,
3816 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3817 cfg80211_inform_bss_frame.
3818 */
3819 struct net_device *dev = pAdapter->dev;
3820 struct wireless_dev *wdev = dev->ieee80211_ptr;
3821 struct wiphy *wiphy = wdev->wiphy;
3822 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003823#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3824 qcom_ie_age *qie_age = NULL;
3825 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3826#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003827 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003828#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003829 const char *ie =
3830 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3831 unsigned int freq;
3832 struct ieee80211_channel *chan;
3833 struct ieee80211_mgmt *mgmt =
3834 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3835 struct cfg80211_bss *bss_status = NULL;
3836 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3837 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003838#ifdef WLAN_OPEN_SOURCE
3839 struct timespec ts;
3840#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003841
3842 ENTER();
3843
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003844 if (!mgmt)
3845 return NULL;
3846
Jeff Johnson295189b2012-06-20 16:38:30 -07003847 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003848
3849#ifdef WLAN_OPEN_SOURCE
3850 /* Android does not want the timestamp from the frame.
3851 Instead it wants a monotonic increasing value */
3852 get_monotonic_boottime(&ts);
3853 mgmt->u.probe_resp.timestamp =
3854 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3855#else
3856 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003857 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3858 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003859
3860#endif
3861
Jeff Johnson295189b2012-06-20 16:38:30 -07003862 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3863 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003864
3865#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3866 /* GPS Requirement: need age ie per entry. Using vendor specific. */
3867 /* Assuming this is the last IE, copy at the end */
3868 ie_length -=sizeof(qcom_ie_age);
3869 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
3870 qie_age->element_id = QCOM_VENDOR_IE_ID;
3871 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
3872 qie_age->oui_1 = QCOM_OUI1;
3873 qie_age->oui_2 = QCOM_OUI2;
3874 qie_age->oui_3 = QCOM_OUI3;
3875 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
3876 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
3877#endif
3878
Jeff Johnson295189b2012-06-20 16:38:30 -07003879 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3880
3881 mgmt->frame_control |=
3882 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3883
3884#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3885 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3886 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3887 {
3888 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3889 }
3890 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3891 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3892
3893 {
3894 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3895 }
3896 else
3897 {
3898 kfree(mgmt);
3899 return NULL;
3900 }
3901#else
3902 freq = ieee80211_channel_to_frequency(chan_no);
3903#endif
3904 chan = __ieee80211_get_channel(wiphy, freq);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08003905 /*when the band is changed on the fly using the GUI, three things are done
3906 * 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)
3907 * as part of the scan abort, message willbe queued to PE and we proceed with flushing and changinh the band.
3908 * pe will stop the scanning further and report back the results what ever it had till now by calling the call back function.
3909 * if the time between update band and scandone call back is sufficent enough the band change reflects in SME, SME validates the channels
3910 * and discards the channels correponding to previous band and calls back with zero bss results.
3911 * 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
3912 * all the channels correponding to previous band.this is due to race condition.but those channels are invalid to the new band and so
3913 * this function __ieee80211_get_channel will return NULL.Each time we report scan result with this pointer null warning kernel trace is printed.
3914 * if the scan results contain large number of APs continuosly kernel warning trace is printed and it will lead to apps watch dog bark.
3915 * So drop the bss and continue to next bss.
3916 */
3917 if(chan == NULL)
3918 {
3919 hddLog(VOS_TRACE_LEVEL_INFO, "%s chan pointer is NULL", __func__);
3920 return NULL;
3921 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003922 /*To keep the rssi icon of the connected AP in the scan window
3923 *and the rssi icon of the wireless networks in sync
3924 * */
3925 if (( eConnectionState_Associated ==
3926 pAdapter->sessionCtx.station.conn_info.connState ) &&
3927 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3928 pAdapter->sessionCtx.station.conn_info.bssId,
3929 WNI_CFG_BSSID_LEN)))
3930 {
3931 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3932 rssi = (pAdapter->rssi * 100);
3933 }
3934 else
3935 {
3936 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3937 }
3938
3939 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3940 frame_len, rssi, GFP_KERNEL);
3941 kfree(mgmt);
3942 return bss_status;
3943}
3944
3945/*
3946 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3947 * This function is used to update the BSS data base of CFG8011
3948 */
3949struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3950 tCsrRoamInfo *pRoamInfo
3951 )
3952{
3953 tCsrRoamConnectedProfile roamProfile;
3954 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3955 struct cfg80211_bss *bss = NULL;
3956
3957 ENTER();
3958
3959 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
3960 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
3961
3962 if (NULL != roamProfile.pBssDesc)
3963 {
3964 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
3965 &roamProfile);
3966
3967 if (NULL == bss)
3968 {
3969 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
3970 __func__);
3971 }
3972
3973 sme_RoamFreeConnectProfile(hHal, &roamProfile);
3974 }
3975 else
3976 {
3977 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
3978 __func__);
3979 }
3980 return bss;
3981}
3982
3983/*
3984 * FUNCTION: wlan_hdd_cfg80211_update_bss
3985 */
3986static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
3987 hdd_adapter_t *pAdapter
3988 )
3989{
3990 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3991 tCsrScanResultInfo *pScanResult;
3992 eHalStatus status = 0;
3993 tScanResultHandle pResult;
3994 struct cfg80211_bss *bss_status = NULL;
3995
3996 ENTER();
3997
3998 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3999 {
4000 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
4001 return -EAGAIN;
4002 }
4003
4004 /*
4005 * start getting scan results and populate cgf80211 BSS database
4006 */
4007 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
4008
4009 /* no scan results */
4010 if (NULL == pResult)
4011 {
4012 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
4013 return status;
4014 }
4015
4016 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
4017
4018 while (pScanResult)
4019 {
4020 /*
4021 * cfg80211_inform_bss() is not updating ie field of bss entry, if
4022 * entry already exists in bss data base of cfg80211 for that
4023 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
4024 * bss entry instead of cfg80211_inform_bss, But this call expects
4025 * mgmt packet as input. As of now there is no possibility to get
4026 * the mgmt(probe response) frame from PE, converting bss_desc to
4027 * ieee80211_mgmt(probe response) and passing to c
4028 * fg80211_inform_bss_frame.
4029 * */
4030
4031 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
4032 &pScanResult->BssDescriptor);
4033
4034
4035 if (NULL == bss_status)
4036 {
4037 hddLog(VOS_TRACE_LEVEL_INFO,
4038 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
4039 }
4040 else
4041 {
4042 cfg80211_put_bss(bss_status);
4043 }
4044
4045 pScanResult = sme_ScanResultGetNext(hHal, pResult);
4046 }
4047
4048 sme_ScanResultPurge(hHal, pResult);
4049
4050 return 0;
4051}
4052
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004053void
4054hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
4055{
4056 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004057 "%02X:%02X:%02X:%02X:%02X:%02X\n",
4058 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
4059 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004060} /****** end hddPrintMacAddr() ******/
4061
4062void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004063hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004064{
4065 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004066 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
4067 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
4068 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
4069 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004070} /****** end hddPrintPmkId() ******/
4071
4072//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
4073//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
4074
4075//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
4076//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
4077
4078#define dump_bssid(bssid) \
4079 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004080 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
4081 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
4082 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004083 }
4084
4085#define dump_pmkid(pMac, pmkid) \
4086 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004087 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
4088 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
4089 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004090 }
4091
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07004092#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004093/*
4094 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
4095 * This function is used to notify the supplicant of a new PMKSA candidate.
4096 */
4097int wlan_hdd_cfg80211_pmksa_candidate_notify(
4098 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
4099 int index, bool preauth )
4100{
Jeff Johnsone7245742012-09-05 17:12:55 -07004101#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004102 struct net_device *dev = pAdapter->dev;
4103
4104 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07004105 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004106
4107 if( NULL == pRoamInfo )
4108 {
4109 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
4110 return -EINVAL;
4111 }
4112
4113 dump_bssid(pRoamInfo->bssid);
4114 cfg80211_pmksa_candidate_notify(dev, index,
4115 pRoamInfo->bssid, preauth, GFP_KERNEL);
Jeff Johnsone7245742012-09-05 17:12:55 -07004116#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004117 return 0;
4118}
4119#endif //FEATURE_WLAN_LFR
4120
Jeff Johnson295189b2012-06-20 16:38:30 -07004121/*
4122 * FUNCTION: hdd_cfg80211_scan_done_callback
4123 * scanning callback function, called after finishing scan
4124 *
4125 */
4126static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
4127 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
4128{
4129 struct net_device *dev = (struct net_device *) pContext;
4130 //struct wireless_dev *wdev = dev->ieee80211_ptr;
4131 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004132 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4133 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004134 struct cfg80211_scan_request *req = NULL;
4135 int ret = 0;
4136
4137 ENTER();
4138
4139 hddLog(VOS_TRACE_LEVEL_INFO,
4140 "%s called with halHandle = %p, pContext = %p,"
4141 "scanID = %d, returned status = %d\n",
4142 __func__, halHandle, pContext, (int) scanId, (int) status);
4143
4144 //Block on scan req completion variable. Can't wait forever though.
4145 ret = wait_for_completion_interruptible_timeout(
4146 &pScanInfo->scan_req_completion_event,
4147 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
4148 if (!ret)
4149 {
4150 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004151 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004152 }
4153
4154 if(pScanInfo->mScanPending != VOS_TRUE)
4155 {
4156 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004157 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004158 }
4159
4160 /* Check the scanId */
4161 if (pScanInfo->scanId != scanId)
4162 {
4163 hddLog(VOS_TRACE_LEVEL_INFO,
4164 "%s called with mismatched scanId pScanInfo->scanId = %d "
4165 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
4166 (int) scanId);
4167 }
4168
Jeff Johnson295189b2012-06-20 16:38:30 -07004169 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
4170 pAdapter);
4171
4172 if (0 > ret)
4173 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
4174
4175
4176 /* If any client wait scan result through WEXT
4177 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004178 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07004179 {
4180 /* The other scan request waiting for current scan finish
4181 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004182 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004183 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004184 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004185 }
4186 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004187 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004188 {
4189 struct net_device *dev = pAdapter->dev;
4190 union iwreq_data wrqu;
4191 int we_event;
4192 char *msg;
4193
4194 memset(&wrqu, '\0', sizeof(wrqu));
4195 we_event = SIOCGIWSCAN;
4196 msg = NULL;
4197 wireless_send_event(dev, we_event, &wrqu, msg);
4198 }
4199 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004200 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004201
4202 /* Get the Scan Req */
4203 req = pAdapter->request;
4204
4205 if (!req)
4206 {
4207 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004208 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07004209 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004210 }
4211
4212 /*
4213 * setting up 0, just in case.
4214 */
4215 req->n_ssids = 0;
4216 req->n_channels = 0;
4217 req->ie = 0;
4218
Jeff Johnson295189b2012-06-20 16:38:30 -07004219 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004220 /* Scan is no longer pending */
4221 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004222
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07004223 /*
4224 * cfg80211_scan_done informing NL80211 about completion
4225 * of scanning
4226 */
4227 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004228 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004229
Jeff Johnsone7245742012-09-05 17:12:55 -07004230allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004231 /* release the wake lock at the end of the scan*/
4232 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004233
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004234 /* Acquire wakelock to handle the case where APP's tries to suspend
4235 * immediatly after the driver gets connect request(i.e after scan)
4236 * from supplicant, this result in app's is suspending and not able
4237 * to process the connect request to AP */
4238 hdd_allow_suspend_timeout(100);
4239
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004240#ifdef FEATURE_WLAN_TDLS
4241 wlan_hdd_tdls_scan_done_callback(pAdapter);
4242#endif
4243
Jeff Johnson295189b2012-06-20 16:38:30 -07004244 EXIT();
4245 return 0;
4246}
4247
4248/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004249 * FUNCTION: hdd_isScanAllowed
4250 * Go through each adapter and check if scan allowed
4251 *
4252 */
4253v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
4254{
4255 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4256 hdd_station_ctx_t *pHddStaCtx = NULL;
4257 hdd_adapter_t *pAdapter = NULL;
4258 VOS_STATUS status = 0;
4259 v_U8_t staId = 0;
4260 v_U8_t *staMac = NULL;
4261
4262 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4263
4264 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4265 {
4266 pAdapter = pAdapterNode->pAdapter;
4267
4268 if( pAdapter )
4269 {
4270 hddLog(VOS_TRACE_LEVEL_INFO,
4271 "%s: Adapter with device mode %d exists",
4272 __func__, pAdapter->device_mode);
4273 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4274 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4275 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
4276 {
4277 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4278 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
4279 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
4280 {
4281 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
4282 hddLog(VOS_TRACE_LEVEL_ERROR,
4283 "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the "
4284 "middle of WPS/EAPOL exchange.", __func__,
4285 staMac[0], staMac[1], staMac[2],
4286 staMac[3], staMac[4], staMac[5]);
4287 return VOS_FALSE;
4288 }
4289 }
4290 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
4291 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
4292 {
4293 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
4294 {
4295 if ((pAdapter->aStaInfo[staId].isUsed) &&
4296 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
4297 {
4298 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
4299
4300 hddLog(VOS_TRACE_LEVEL_ERROR,
4301 "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the "
4302 "middle of WPS/EAPOL exchange.", __func__,
4303 staMac[0], staMac[1], staMac[2],
4304 staMac[3], staMac[4], staMac[5]);
4305 return VOS_FALSE;
4306 }
4307 }
4308 }
4309 }
4310 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4311 pAdapterNode = pNext;
4312 }
4313 hddLog(VOS_TRACE_LEVEL_INFO,
4314 "%s: Scan allowed", __func__);
4315 return VOS_TRUE;
4316}
4317
4318/*
Jeff Johnson295189b2012-06-20 16:38:30 -07004319 * FUNCTION: wlan_hdd_cfg80211_scan
4320 * this scan respond to scan trigger and update cfg80211 scan database
4321 * later, scan dump command can be used to recieve scan results
4322 */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08004323int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
4324#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4325 struct net_device *dev,
4326#endif
4327 struct cfg80211_scan_request *request)
4328{
4329#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4330 struct net_device *dev = request->wdev->netdev;
4331#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004332 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4333 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4334 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4335 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
4336 tCsrScanRequest scanRequest;
4337 tANI_U8 *channelList = NULL, i;
4338 v_U32_t scanId = 0;
4339 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004340 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004341 v_U8_t* pP2pIe = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004342
4343 ENTER();
4344
4345 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4346 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004347
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004348 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004349 (eConnectionState_Connecting ==
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004350 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004351 {
4352 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004353 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
4354 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004355 return -EBUSY;
4356 }
4357
Jeff Johnson295189b2012-06-20 16:38:30 -07004358#ifdef WLAN_BTAMP_FEATURE
4359 //Scan not supported when AMP traffic is on.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004360 if (VOS_TRUE == WLANBAP_AmpSessionOn())
Jeff Johnson295189b2012-06-20 16:38:30 -07004361 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004362 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004363 "%s: No scanning when AMP is on", __func__);
4364 return -EOPNOTSUPP;
4365 }
4366#endif
4367 //Scan on any other interface is not supported.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004368 if (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07004369 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004370 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004371 "%s: Not scanning on device_mode = %d",
4372 __func__, pAdapter->device_mode);
4373 return -EOPNOTSUPP;
4374 }
4375
4376 if (TRUE == pScanInfo->mScanPending)
4377 {
4378 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004379 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07004380 }
4381
4382 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4383 {
4384 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4385 "%s:LOGP in Progress. Ignore!!!", __func__);
4386 return -EAGAIN;
4387 }
4388
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07004389 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
4390 {
4391 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4392 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
4393 return -EAGAIN;
4394 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004395 //Don't Allow Scan and return busy if Remain On
4396 //Channel and action frame is pending
4397 //Otherwise Cancel Remain On Channel and allow Scan
4398 //If no action frame pending
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004399 if (0 != wlan_hdd_check_remain_on_channel(pAdapter))
Jeff Johnson32d95a32012-09-10 13:15:23 -07004400 {
4401 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
4402 return -EBUSY;
4403 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004404#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004405 /* if tdls disagree scan right now, return immediately.
4406 tdls will schedule the scan when scan is allowed. (return SUCCESS)
4407 or will reject the scan if any TDLS is in progress. (return -EBUSY)
4408 */
4409 status = wlan_hdd_tdls_scan_callback (pAdapter,
4410 wiphy,
4411#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4412 dev,
Gopichand Nakkalac3c42b92013-03-20 19:42:34 -07004413#endif
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004414 request);
4415 if(status <= 0)
4416 {
4417 hddLog(VOS_TRACE_LEVEL_INFO, "%s: TDLS Pending %d", __func__, status);
4418 return status;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004419 }
4420#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07004421
Jeff Johnson295189b2012-06-20 16:38:30 -07004422 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
4423 {
4424 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08004425 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004426 return -EAGAIN;
4427 }
4428 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
4429 {
4430 hddLog(VOS_TRACE_LEVEL_WARN,
4431 "%s: MAX TM Level Scan not allowed", __func__);
4432 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4433 return -EBUSY;
4434 }
4435 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4436
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004437 /* Check if scan is allowed at this point of time.
4438 */
4439 if (!hdd_isScanAllowed(pHddCtx))
4440 {
4441 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
4442 return -EBUSY;
4443 }
4444
Jeff Johnson295189b2012-06-20 16:38:30 -07004445 vos_mem_zero( &scanRequest, sizeof(scanRequest));
4446
4447 if (NULL != request)
4448 {
4449 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
4450 (int)request->n_ssids);
4451
4452 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
4453 * Becasue of this, driver is assuming that this is not wildcard scan and so
4454 * is not aging out the scan results.
4455 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07004456 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07004457 {
4458 request->n_ssids = 0;
4459 }
4460
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004461 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07004462 {
4463 tCsrSSIDInfo *SsidInfo;
4464 int j;
4465 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
4466 /* Allocate num_ssid tCsrSSIDInfo structure */
4467 SsidInfo = scanRequest.SSIDs.SSIDList =
4468 ( tCsrSSIDInfo *)vos_mem_malloc(
4469 request->n_ssids*sizeof(tCsrSSIDInfo));
4470
4471 if(NULL == scanRequest.SSIDs.SSIDList)
4472 {
4473 hddLog(VOS_TRACE_LEVEL_ERROR,
4474 "memory alloc failed SSIDInfo buffer");
4475 return -ENOMEM;
4476 }
4477
4478 /* copy all the ssid's and their length */
4479 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
4480 {
4481 /* get the ssid length */
4482 SsidInfo->SSID.length = request->ssids[j].ssid_len;
4483 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
4484 SsidInfo->SSID.length);
4485 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
4486 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
4487 j, SsidInfo->SSID.ssId);
4488 }
4489 /* set the scan type to active */
4490 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4491 }
4492 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4493 {
4494 /* set the scan type to active */
4495 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4496 }
4497 else
4498 {
4499 /*Set the scan type to default type, in this case it is ACTIVE*/
4500 scanRequest.scanType = pScanInfo->scan_mode;
4501 }
4502 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
4503 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4504 }
4505 else
4506 {
4507 /* set the scan type to active */
4508 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4509 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4510
4511 /* set min and max channel time to zero */
4512 scanRequest.minChnTime = 0;
4513 scanRequest.maxChnTime = 0;
4514 }
4515
4516 /* set BSSType to default type */
4517 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4518
4519 /*TODO: scan the requested channels only*/
4520
4521 /*Right now scanning all the channels */
4522 if( request )
4523 {
4524 if( request->n_channels )
4525 {
4526 channelList = vos_mem_malloc( request->n_channels );
4527 if( NULL == channelList )
4528 {
4529 status = -ENOMEM;
4530 goto free_mem;
4531 }
4532
4533 for( i = 0 ; i < request->n_channels ; i++ )
4534 channelList[i] = request->channels[i]->hw_value;
4535 }
4536
4537 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4538 scanRequest.ChannelInfo.ChannelList = channelList;
4539
4540 /* set requestType to full scan */
4541 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004542
4543 /* Flush the scan results(only p2p beacons) for STA scan and P2P
4544 * search (Flush on both full scan and social scan but not on single
4545 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
4546 */
4547
4548 /* Supplicant does single channel scan after 8-way handshake
4549 * and in that case driver shoudnt flush scan results. If
4550 * driver flushes the scan results here and unfortunately if
4551 * the AP doesnt respond to our probe req then association
4552 * fails which is not desired
4553 */
4554
4555 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4556 {
4557 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4558 pAdapter->sessionId );
4559 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004560
4561 if( request->ie_len )
4562 {
4563 /* save this for future association (join requires this) */
4564 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4565 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4566 pScanInfo->scanAddIE.length = request->ie_len;
4567
4568 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004569 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4570 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004571 )
4572 {
4573 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4574 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4575 }
4576
4577 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4578 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4579
Jeff Johnson295189b2012-06-20 16:38:30 -07004580 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4581 request->ie_len);
4582 if (pP2pIe != NULL)
4583 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004584#ifdef WLAN_FEATURE_P2P_DEBUG
4585 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4586 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4587 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4588 {
4589 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4590 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4591 "Go nego completed to Connection is started");
4592 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4593 "for 8way Handshake");
4594 }
4595 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4596 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4597 {
4598 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4599 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4600 "Disconnected state to Connection is started");
4601 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4602 "for 4way Handshake");
4603 }
4604#endif
4605
Jeff Johnsone7245742012-09-05 17:12:55 -07004606 /* no_cck will be set during p2p find to disable 11b rates */
4607 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004608 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004609 hddLog(VOS_TRACE_LEVEL_INFO,
4610 "%s: This is a P2P Search", __func__);
4611 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004612
Jeff Johnsone7245742012-09-05 17:12:55 -07004613 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4614 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004615 /* set requestType to P2P Discovery */
4616 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004617 }
4618
4619 /*
4620 Skip Dfs Channel in case of P2P Search
4621 if it is set in ini file
4622 */
4623 if(cfg_param->skipDfsChnlInP2pSearch)
4624 {
4625 scanRequest.skipDfsChnlInP2pSearch = 1;
4626 }
4627 else
4628 {
4629 scanRequest.skipDfsChnlInP2pSearch = 0;
4630 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004631
Jeff Johnson295189b2012-06-20 16:38:30 -07004632 }
4633 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004634 }
4635 }
4636
4637 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4638
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004639 /* acquire the wakelock to avoid the apps suspend during the scan. To
4640 * address the following issues.
4641 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4642 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4643 * for long time, this result in apps running at full power for long time.
4644 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4645 * be stuck in full power because of resume BMPS
4646 */
4647 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004648
4649 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004650 pAdapter->sessionId, &scanRequest, &scanId,
4651 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004652
Jeff Johnson295189b2012-06-20 16:38:30 -07004653 if (eHAL_STATUS_SUCCESS != status)
4654 {
4655 hddLog(VOS_TRACE_LEVEL_ERROR,
4656 "%s: sme_ScanRequest returned error %d", __func__, status);
4657 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004658 if(eHAL_STATUS_RESOURCES == status)
4659 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004660 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 -07004661 status = -EBUSY;
4662 } else {
4663 status = -EIO;
4664 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004665 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004666 goto free_mem;
4667 }
4668
4669 pScanInfo->mScanPending = TRUE;
4670 pAdapter->request = request;
4671 pScanInfo->scanId = scanId;
4672
4673 complete(&pScanInfo->scan_req_completion_event);
4674
4675free_mem:
4676 if( scanRequest.SSIDs.SSIDList )
4677 {
4678 vos_mem_free(scanRequest.SSIDs.SSIDList);
4679 }
4680
4681 if( channelList )
4682 vos_mem_free( channelList );
4683
4684 EXIT();
4685
4686 return status;
4687}
4688
4689/*
4690 * FUNCTION: wlan_hdd_cfg80211_connect_start
4691 * This function is used to start the association process
4692 */
4693int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004694 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004695{
4696 int status = 0;
4697 hdd_wext_state_t *pWextState;
4698 v_U32_t roamId;
4699 tCsrRoamProfile *pRoamProfile;
4700 eMib_dot11DesiredBssType connectedBssType;
4701 eCsrAuthType RSNAuthType;
4702
4703 ENTER();
4704
4705 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4706
4707 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4708 {
4709 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4710 return -EINVAL;
4711 }
4712
4713 pRoamProfile = &pWextState->roamProfile;
4714
4715 if (pRoamProfile)
4716 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004717 int ret = 0;
4718 hdd_station_ctx_t *pHddStaCtx;
4719 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4720 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4721
4722 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4723 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4724 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004725 {
4726 /* Issue disconnect to CSR */
4727 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4728 if( eHAL_STATUS_SUCCESS ==
4729 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4730 pAdapter->sessionId,
4731 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4732 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004733 ret = wait_for_completion_interruptible_timeout(
4734 &pAdapter->disconnect_comp_var,
4735 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4736 if (0 == ret)
4737 {
4738 VOS_ASSERT(0);
4739 }
4740 }
4741 }
4742 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4743 {
4744 ret = wait_for_completion_interruptible_timeout(
4745 &pAdapter->disconnect_comp_var,
4746 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4747 if (0 == ret)
4748 {
4749 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004750 }
4751 }
4752
4753 if (HDD_WMM_USER_MODE_NO_QOS ==
4754 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4755 {
4756 /*QoS not enabled in cfg file*/
4757 pRoamProfile->uapsd_mask = 0;
4758 }
4759 else
4760 {
4761 /*QoS enabled, update uapsd mask from cfg file*/
4762 pRoamProfile->uapsd_mask =
4763 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4764 }
4765
4766 pRoamProfile->SSIDs.numOfSSIDs = 1;
4767 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4768 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
4769 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
4770 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4771 ssid, ssid_len);
4772
4773 if (bssid)
4774 {
4775 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4776 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4777 WNI_CFG_BSSID_LEN);
4778 /* Save BSSID in seperate variable as well, as RoamProfile
4779 BSSID is getting zeroed out in the association process. And in
4780 case of join failure we should send valid BSSID to supplicant
4781 */
4782 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4783 WNI_CFG_BSSID_LEN);
4784 }
4785
4786 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4787 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4788 {
4789 /*set gen ie*/
4790 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4791 /*set auth*/
4792 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4793 }
4794 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4795 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4796 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4797 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4798 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4799 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4800 )
4801 {
4802 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4803 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4804 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4805 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4806 eCSR_AUTH_TYPE_AUTOSWITCH;
4807 pWextState->roamProfile.AuthType.authType[0] =
4808 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4809 }
4810#ifdef FEATURE_WLAN_WAPI
4811 if (pAdapter->wapi_info.nWapiMode)
4812 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004813 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004814 switch (pAdapter->wapi_info.wapiAuthMode)
4815 {
4816 case WAPI_AUTH_MODE_PSK:
4817 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004818 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004819 pAdapter->wapi_info.wapiAuthMode);
4820 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4821 break;
4822 }
4823 case WAPI_AUTH_MODE_CERT:
4824 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004825 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004826 pAdapter->wapi_info.wapiAuthMode);
4827 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4828 break;
4829 }
4830 } // End of switch
4831 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4832 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4833 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004834 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004835 pRoamProfile->AuthType.numEntries = 1;
4836 pRoamProfile->EncryptionType.numEntries = 1;
4837 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4838 pRoamProfile->mcEncryptionType.numEntries = 1;
4839 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4840 }
4841 }
4842#endif /* FEATURE_WLAN_WAPI */
4843 pRoamProfile->csrPersona = pAdapter->device_mode;
4844
Jeff Johnson32d95a32012-09-10 13:15:23 -07004845 if( operatingChannel )
4846 {
4847 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4848 pRoamProfile->ChannelInfo.numOfChannels = 1;
4849 }
Chet Lanctot186b5732013-03-18 10:26:30 -07004850 else
4851 {
4852 pRoamProfile->ChannelInfo.ChannelList = NULL;
4853 pRoamProfile->ChannelInfo.numOfChannels = 0;
4854 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004855
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004856 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
4857 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
4858 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
4859 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004860 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
4861 */
4862 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4863 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
4864 eConnectionState_Connecting);
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004865
Jeff Johnson295189b2012-06-20 16:38:30 -07004866 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4867 pAdapter->sessionId, pRoamProfile, &roamId);
4868
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004869 if( (eHAL_STATUS_SUCCESS != status) &&
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304870 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
4871
4872 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004873 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
4874 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
4875 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304876 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004877 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304878 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004879
4880 pRoamProfile->ChannelInfo.ChannelList = NULL;
4881 pRoamProfile->ChannelInfo.numOfChannels = 0;
4882
Jeff Johnson295189b2012-06-20 16:38:30 -07004883 }
4884 else
4885 {
4886 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4887 return -EINVAL;
4888 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004889 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004890 return status;
4891}
4892
4893/*
4894 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4895 * This function is used to set the authentication type (OPEN/SHARED).
4896 *
4897 */
4898static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4899 enum nl80211_auth_type auth_type)
4900{
4901 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4902 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4903
4904 ENTER();
4905
4906 /*set authentication type*/
4907 switch (auth_type)
4908 {
4909 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4910 case NL80211_AUTHTYPE_AUTOMATIC:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07004911#ifdef WLAN_FEATURE_VOWIFI_11R
4912 case NL80211_AUTHTYPE_FT:
4913#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07004914 hddLog(VOS_TRACE_LEVEL_INFO,
4915 "%s: set authentication type to OPEN", __func__);
4916 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4917 break;
4918
4919 case NL80211_AUTHTYPE_SHARED_KEY:
4920 hddLog(VOS_TRACE_LEVEL_INFO,
4921 "%s: set authentication type to SHARED", __func__);
4922 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4923 break;
4924#ifdef FEATURE_WLAN_CCX
4925 case NL80211_AUTHTYPE_NETWORK_EAP:
4926 hddLog(VOS_TRACE_LEVEL_INFO,
4927 "%s: set authentication type to CCKM WPA", __func__);
4928 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4929 break;
4930#endif
4931
4932
4933 default:
4934 hddLog(VOS_TRACE_LEVEL_ERROR,
4935 "%s: Unsupported authentication type %d", __func__,
4936 auth_type);
4937 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4938 return -EINVAL;
4939 }
4940
4941 pWextState->roamProfile.AuthType.authType[0] =
4942 pHddStaCtx->conn_info.authType;
4943 return 0;
4944}
4945
4946/*
4947 * FUNCTION: wlan_hdd_set_akm_suite
4948 * This function is used to set the key mgmt type(PSK/8021x).
4949 *
4950 */
4951static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
4952 u32 key_mgmt
4953 )
4954{
4955 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4956 ENTER();
4957
4958 /*set key mgmt type*/
4959 switch(key_mgmt)
4960 {
4961 case WLAN_AKM_SUITE_PSK:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05304962#ifdef WLAN_FEATURE_VOWIFI_11R
4963 case WLAN_AKM_SUITE_FT_PSK:
4964#endif
4965 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
Jeff Johnson295189b2012-06-20 16:38:30 -07004966 __func__);
4967 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
4968 break;
4969
4970 case WLAN_AKM_SUITE_8021X:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05304971#ifdef WLAN_FEATURE_VOWIFI_11R
4972 case WLAN_AKM_SUITE_FT_8021X:
4973#endif
4974 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
Jeff Johnson295189b2012-06-20 16:38:30 -07004975 __func__);
4976 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
4977 break;
4978#ifdef FEATURE_WLAN_CCX
4979#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
4980#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
4981 case WLAN_AKM_SUITE_CCKM:
4982 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
4983 __func__);
4984 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
4985 break;
4986#endif
4987
4988 default:
4989 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
4990 __func__, key_mgmt);
4991 return -EINVAL;
4992
4993 }
4994 return 0;
4995}
4996
4997/*
4998 * FUNCTION: wlan_hdd_cfg80211_set_cipher
4999 * This function is used to set the encryption type
5000 * (NONE/WEP40/WEP104/TKIP/CCMP).
5001 */
5002static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
5003 u32 cipher,
5004 bool ucast
5005 )
5006{
5007 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5008 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5009 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5010
5011 ENTER();
5012
5013 if (!cipher)
5014 {
5015 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
5016 __func__, cipher);
5017 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5018 }
5019 else
5020 {
5021
5022 /*set encryption method*/
5023 switch (cipher)
5024 {
5025 case IW_AUTH_CIPHER_NONE:
5026 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5027 break;
5028
5029 case WLAN_CIPHER_SUITE_WEP40:
5030 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
5031 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
5032 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
5033 else
5034 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5035 break;
5036
5037 case WLAN_CIPHER_SUITE_WEP104:
5038 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
5039 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
5040 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
5041 else
5042 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
5043 break;
5044
5045 case WLAN_CIPHER_SUITE_TKIP:
5046 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5047 break;
5048
5049 case WLAN_CIPHER_SUITE_CCMP:
5050 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5051 break;
5052#ifdef FEATURE_WLAN_WAPI
5053 case WLAN_CIPHER_SUITE_SMS4:
5054 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
5055 break;
5056#endif
5057
5058#ifdef FEATURE_WLAN_CCX
5059 case WLAN_CIPHER_SUITE_KRK:
5060 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
5061 break;
5062#endif
5063 default:
5064 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
5065 __func__, cipher);
5066 return -EOPNOTSUPP;
5067 }
5068 }
5069
5070 if (ucast)
5071 {
5072 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
5073 __func__, encryptionType);
5074 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5075 pWextState->roamProfile.EncryptionType.numEntries = 1;
5076 pWextState->roamProfile.EncryptionType.encryptionType[0] =
5077 encryptionType;
5078 }
5079 else
5080 {
5081 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
5082 __func__, encryptionType);
5083 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
5084 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
5085 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
5086 }
5087
5088 return 0;
5089}
5090
5091
5092/*
5093 * FUNCTION: wlan_hdd_cfg80211_set_ie
5094 * This function is used to parse WPA/RSN IE's.
5095 */
5096int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
5097 u8 *ie,
5098 size_t ie_len
5099 )
5100{
5101 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5102 u8 *genie = ie;
5103 v_U16_t remLen = ie_len;
5104#ifdef FEATURE_WLAN_WAPI
5105 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
5106 u16 *tmp;
5107 v_U16_t akmsuiteCount;
5108 int *akmlist;
5109#endif
5110 ENTER();
5111
5112 /* clear previous assocAddIE */
5113 pWextState->assocAddIE.length = 0;
5114 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
5115
5116 while (remLen >= 2)
5117 {
5118 v_U16_t eLen = 0;
5119 v_U8_t elementId;
5120 elementId = *genie++;
5121 eLen = *genie++;
5122 remLen -= 2;
5123
5124 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
5125 __func__, elementId, eLen);
5126
5127 switch ( elementId )
5128 {
5129 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005130 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 -07005131 {
5132 hddLog(VOS_TRACE_LEVEL_ERROR,
5133 "%s: Invalid WPA IE", __func__);
5134 return -EINVAL;
5135 }
5136 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
5137 {
5138 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5139 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
5140 __func__, eLen + 2);
5141
5142 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5143 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005144 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
5145 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005146 VOS_ASSERT(0);
5147 return -ENOMEM;
5148 }
5149 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5150 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5151 pWextState->assocAddIE.length += eLen + 2;
5152
5153 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
5154 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5155 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5156 }
5157 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
5158 {
5159 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
5160 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5161 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
5162 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
5163 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
5164 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005165 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
5166 P2P_OUI_TYPE_SIZE))
5167 /*Consider P2P IE, only for P2P Client */
5168 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5169 {
5170 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5171 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
5172 __func__, eLen + 2);
5173
5174 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5175 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005176 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5177 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005178 VOS_ASSERT(0);
5179 return -ENOMEM;
5180 }
5181 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5182 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5183 pWextState->assocAddIE.length += eLen + 2;
5184
5185 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5186 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5187 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005188#ifdef WLAN_FEATURE_WFD
5189 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
5190 WFD_OUI_TYPE_SIZE))
5191 /*Consider WFD IE, only for P2P Client */
5192 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5193 {
5194 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5195 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
5196 __func__, eLen + 2);
5197
5198 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5199 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005200 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5201 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005202 VOS_ASSERT(0);
5203 return -ENOMEM;
5204 }
5205 // WFD IE is saved to Additional IE ; it should be accumulated to handle
5206 // WPS IE + P2P IE + WFD IE
5207 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5208 pWextState->assocAddIE.length += eLen + 2;
5209
5210 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5211 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5212 }
5213#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005214 /* Appending HS 2.0 Indication Element in Assiciation Request */
5215 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005216 HS20_OUI_TYPE_SIZE)) )
5217 {
5218 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5219 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
5220 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005221
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005222 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5223 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005224 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5225 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005226 VOS_ASSERT(0);
5227 return -ENOMEM;
5228 }
5229 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5230 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005231
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005232 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5233 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5234 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005235
Jeff Johnson295189b2012-06-20 16:38:30 -07005236 break;
5237 case DOT11F_EID_RSN:
5238 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
5239 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5240 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
5241 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
5242 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
5243 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005244 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
5245 case DOT11F_EID_EXTCAP:
5246 {
5247 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5248 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
5249 __func__, eLen + 2);
5250
5251 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5252 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005253 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5254 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005255 VOS_ASSERT(0);
5256 return -ENOMEM;
5257 }
5258 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5259 pWextState->assocAddIE.length += eLen + 2;
5260
5261 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5262 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5263 break;
5264 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005265#ifdef FEATURE_WLAN_WAPI
5266 case WLAN_EID_WAPI:
5267 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
5268 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
5269 pAdapter->wapi_info.nWapiMode);
5270 tmp = (u16 *)ie;
5271 tmp = tmp + 2; // Skip element Id and Len, Version
5272 akmsuiteCount = WPA_GET_LE16(tmp);
5273 tmp = tmp + 1;
5274 akmlist = (int *)(tmp);
5275 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
5276 {
5277 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
5278 }
5279 else
5280 {
5281 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
5282 VOS_ASSERT(0);
5283 return -EINVAL;
5284 }
5285
5286 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
5287 {
5288 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005289 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005290 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
5291 }
5292 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
5293 {
5294 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005295 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005296 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
5297 }
5298 break;
5299#endif
5300 default:
5301 hddLog (VOS_TRACE_LEVEL_ERROR,
5302 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005303 /* when Unknown IE is received we should break and continue
5304 * to the next IE in the buffer instead we were returning
5305 * so changing this to break */
5306 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005307 }
5308 genie += eLen;
5309 remLen -= eLen;
5310 }
5311 EXIT();
5312 return 0;
5313}
5314
5315/*
5316 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5317 * This function is used to initialize the security
5318 * parameters during connect operation.
5319 */
5320int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
5321 struct cfg80211_connect_params *req
5322 )
5323{
5324 int status = 0;
5325 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5326 ENTER();
5327
5328 /*set wpa version*/
5329 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5330
5331 if (req->crypto.wpa_versions)
5332 {
5333 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
5334 && ( (req->ie_len)
5335 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
5336 // Make sure that it is including a WPA IE.
5337 /* Currently NL is putting WPA version 1 even for open,
5338 * since p2p ie is also put in same buffer.
5339 * */
5340 {
5341 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5342 }
5343 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
5344 {
5345 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5346 }
5347 }
5348
5349 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
5350 pWextState->wpaVersion);
5351
5352 /*set authentication type*/
5353 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
5354
5355 if (0 > status)
5356 {
5357 hddLog(VOS_TRACE_LEVEL_ERROR,
5358 "%s: failed to set authentication type ", __func__);
5359 return status;
5360 }
5361
5362 /*set key mgmt type*/
5363 if (req->crypto.n_akm_suites)
5364 {
5365 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
5366 if (0 > status)
5367 {
5368 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
5369 __func__);
5370 return status;
5371 }
5372 }
5373
5374 /*set pairwise cipher type*/
5375 if (req->crypto.n_ciphers_pairwise)
5376 {
5377 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
5378 req->crypto.ciphers_pairwise[0], true);
5379 if (0 > status)
5380 {
5381 hddLog(VOS_TRACE_LEVEL_ERROR,
5382 "%s: failed to set unicast cipher type", __func__);
5383 return status;
5384 }
5385 }
5386 else
5387 {
5388 /*Reset previous cipher suite to none*/
5389 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
5390 if (0 > status)
5391 {
5392 hddLog(VOS_TRACE_LEVEL_ERROR,
5393 "%s: failed to set unicast cipher type", __func__);
5394 return status;
5395 }
5396 }
5397
5398 /*set group cipher type*/
5399 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
5400 false);
5401
5402 if (0 > status)
5403 {
5404 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
5405 __func__);
5406 return status;
5407 }
5408
Chet Lanctot186b5732013-03-18 10:26:30 -07005409#ifdef WLAN_FEATURE_11W
5410 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
5411#endif
5412
Jeff Johnson295189b2012-06-20 16:38:30 -07005413 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
5414 if (req->ie_len)
5415 {
5416 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
5417 if ( 0 > status)
5418 {
5419 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
5420 __func__);
5421 return status;
5422 }
5423 }
5424
5425 /*incase of WEP set default key information*/
5426 if (req->key && req->key_len)
5427 {
5428 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
5429 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
5430 )
5431 {
5432 if ( IW_AUTH_KEY_MGMT_802_1X
5433 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
5434 {
5435 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
5436 __func__);
5437 return -EOPNOTSUPP;
5438 }
5439 else
5440 {
5441 u8 key_len = req->key_len;
5442 u8 key_idx = req->key_idx;
5443
5444 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
5445 && (CSR_MAX_NUM_KEY > key_idx)
5446 )
5447 {
5448 hddLog(VOS_TRACE_LEVEL_INFO,
5449 "%s: setting default wep key, key_idx = %hu key_len %hu",
5450 __func__, key_idx, key_len);
5451 vos_mem_copy(
5452 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
5453 req->key, key_len);
5454 pWextState->roamProfile.Keys.KeyLength[key_idx] =
5455 (u8)key_len;
5456 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
5457 }
5458 }
5459 }
5460 }
5461
5462 return status;
5463}
5464
5465/*
5466 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5467 * This function is used to initialize the security
5468 * parameters during connect operation.
5469 */
5470static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
5471 struct net_device *ndev,
5472 struct cfg80211_connect_params *req
5473 )
5474{
5475 int status = 0;
5476 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
5477 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
5478 hdd_context_t *pHddCtx = NULL;
5479
5480 ENTER();
5481
5482 hddLog(VOS_TRACE_LEVEL_INFO,
5483 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5484
5485 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5486 {
5487 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5488 "%s:LOGP in Progress. Ignore!!!", __func__);
5489 return -EAGAIN;
5490 }
5491
5492#ifdef WLAN_BTAMP_FEATURE
5493 //Infra connect not supported when AMP traffic is on.
5494 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
5495 {
5496 hddLog(VOS_TRACE_LEVEL_ERROR,
5497 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005498 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07005499 }
5500#endif
5501 /*initialise security parameters*/
5502 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
5503
5504 if ( 0 > status)
5505 {
5506 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
5507 __func__);
5508 return status;
5509 }
5510
5511 //If Device Mode is Station Concurrent Sessions Exit BMps
Jeff Johnsona8a1a482012-12-12 16:49:33 -08005512 //P2P Mode will be taken care in Open/close adapter
Jeff Johnson295189b2012-06-20 16:38:30 -07005513 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
5514 (vos_concurrent_sessions_running()))
5515 {
5516 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5517
5518 if (NULL != pVosContext)
5519 {
5520 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5521 if(NULL != pHddCtx)
5522 {
5523 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
5524 }
5525 }
5526 }
5527
Mohit Khanna765234a2012-09-11 15:08:35 -07005528 if ( req->channel )
5529 {
5530 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5531 req->ssid_len, req->bssid,
5532 req->channel->hw_value);
5533 }
5534 else
5535 {
5536 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5537 req->ssid_len, req->bssid,
5538 0);
5539 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005540
5541 if (0 > status)
5542 {
5543 //ReEnable BMPS if disabled
5544 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5545 (NULL != pHddCtx))
5546 {
5547 //ReEnable Bmps and Imps back
5548 hdd_enable_bmps_imps(pHddCtx);
5549 }
5550
5551 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5552 return status;
5553 }
5554 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
5555 EXIT();
5556 return status;
5557}
5558
5559
5560/*
5561 * FUNCTION: wlan_hdd_cfg80211_disconnect
5562 * This function is used to issue a disconnect request to SME
5563 */
5564static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
5565 struct net_device *dev,
5566 u16 reason
5567 )
5568{
5569 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5570 tCsrRoamProfile *pRoamProfile =
5571 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
5572 int status = 0;
5573 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005574#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005575 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005576 tANI_U8 staIdx;
5577#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005578
5579 ENTER();
5580
5581 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
5582 __func__,pAdapter->device_mode);
5583
5584 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5585 __func__, reason);
5586
5587 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
5588 {
5589 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5590 "%s:LOGP in Progress. Ignore!!!",__func__);
5591 return -EAGAIN;
5592 }
5593 if (NULL != pRoamProfile)
5594 {
5595 /*issue disconnect request to SME, if station is in connected state*/
5596 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
5597 {
5598 eCsrRoamDisconnectReason reasonCode =
5599 eCSR_DISCONNECT_REASON_UNSPECIFIED;
5600 switch(reason)
5601 {
5602 case WLAN_REASON_MIC_FAILURE:
5603 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
5604 break;
5605
5606 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
5607 case WLAN_REASON_DISASSOC_AP_BUSY:
5608 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
5609 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
5610 break;
5611
5612 case WLAN_REASON_PREV_AUTH_NOT_VALID:
5613 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
5614 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
5615 break;
5616
5617 case WLAN_REASON_DEAUTH_LEAVING:
5618 default:
5619 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
5620 break;
5621 }
5622 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5623 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
5624 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5625
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005626#ifdef FEATURE_WLAN_TDLS
5627 /* First clean up the tdls peers if any */
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005628 for (staIdx = 0 ; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005629 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005630 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId == pAdapter->sessionId) &&
5631 (pHddCtx->tdlsConnInfo[staIdx].staId))
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005632 {
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005633 uint8 *mac;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005634 mac = pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005635 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07005636 "%s: call sme_DeleteTdlsPeerSta staId %d sessionId %d " MAC_ADDRESS_STR,
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005637 __func__, pHddCtx->tdlsConnInfo[staIdx].staId, pAdapter->sessionId,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07005638 MAC_ADDR_ARRAY(mac));
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005639 sme_DeleteTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005640 pAdapter->sessionId,
5641 mac);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005642 }
5643 }
5644#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005645 /*issue disconnect*/
5646 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5647 pAdapter->sessionId, reasonCode);
5648
5649 if ( 0 != status)
5650 {
5651 hddLog(VOS_TRACE_LEVEL_ERROR,
5652 "%s csrRoamDisconnect failure, returned %d \n",
5653 __func__, (int)status );
5654 return -EINVAL;
5655 }
5656
5657 wait_for_completion_interruptible_timeout(
5658 &pAdapter->disconnect_comp_var,
5659 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5660
5661
5662 /*stop tx queues*/
5663 netif_tx_disable(dev);
5664 netif_carrier_off(dev);
5665 }
5666 }
5667 else
5668 {
5669 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
5670 }
5671
5672 return status;
5673}
5674
5675/*
5676 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
5677 * This function is used to initialize the security
5678 * settings in IBSS mode.
5679 */
5680static int wlan_hdd_cfg80211_set_privacy_ibss(
5681 hdd_adapter_t *pAdapter,
5682 struct cfg80211_ibss_params *params
5683 )
5684{
5685 int status = 0;
5686 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5687 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5688 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5689
5690 ENTER();
5691
5692 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5693
5694 if (params->ie_len && ( NULL != params->ie) )
5695 {
5696 if (WLAN_EID_RSN == params->ie[0])
5697 {
5698 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5699 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5700 }
5701 else
5702 {
5703 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5704 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5705 }
5706 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
5707
5708 if (0 > status)
5709 {
5710 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
5711 __func__);
5712 return status;
5713 }
5714 }
5715
5716 pWextState->roamProfile.AuthType.authType[0] =
5717 pHddStaCtx->conn_info.authType =
5718 eCSR_AUTH_TYPE_OPEN_SYSTEM;
5719
5720 if (params->privacy)
5721 {
5722 /* Security enabled IBSS, At this time there is no information available
5723 * about the security paramters, so initialise the encryption type to
5724 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
5725 * The correct security parameters will be updated later in
5726 * wlan_hdd_cfg80211_add_key */
5727 /* Hal expects encryption type to be set inorder
5728 *enable privacy bit in beacons */
5729
5730 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5731 }
5732
5733 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5734 pWextState->roamProfile.EncryptionType.numEntries = 1;
5735 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
5736
5737 return status;
5738}
5739
5740/*
5741 * FUNCTION: wlan_hdd_cfg80211_join_ibss
5742 * This function is used to create/join an IBSS
5743 */
5744static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
5745 struct net_device *dev,
5746 struct cfg80211_ibss_params *params
5747 )
5748{
5749 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5750 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5751 tCsrRoamProfile *pRoamProfile;
5752 int status;
5753 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5754
5755 ENTER();
5756
5757 hddLog(VOS_TRACE_LEVEL_INFO,
5758 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5759
5760 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5761 {
5762 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5763 "%s:LOGP in Progress. Ignore!!!", __func__);
5764 return -EAGAIN;
5765 }
5766
5767 if (NULL == pWextState)
5768 {
5769 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5770 __func__);
5771 return -EIO;
5772 }
5773
5774 pRoamProfile = &pWextState->roamProfile;
5775
5776 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
5777 {
5778 hddLog (VOS_TRACE_LEVEL_ERROR,
5779 "%s Interface type is not set to IBSS \n", __func__);
5780 return -EINVAL;
5781 }
5782
5783 /* Set Channel */
5784 if (NULL != params->channel)
5785 {
5786 u8 channelNum;
5787 if (IEEE80211_BAND_5GHZ == params->channel->band)
5788 {
5789 hddLog(VOS_TRACE_LEVEL_ERROR,
5790 "%s: IBSS join is called with unsupported band %d",
5791 __func__, params->channel->band);
5792 return -EOPNOTSUPP;
5793 }
5794
5795 /* Get channel number */
5796 channelNum =
5797 ieee80211_frequency_to_channel(params->channel->center_freq);
5798
5799 /*TODO: use macro*/
5800 if (14 >= channelNum)
5801 {
5802 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5803 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5804 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5805 int indx;
5806
5807 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5808 validChan, &numChans))
5809 {
5810 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
5811 __func__);
5812 return -EOPNOTSUPP;
5813 }
5814
5815 for (indx = 0; indx < numChans; indx++)
5816 {
5817 if (channelNum == validChan[indx])
5818 {
5819 break;
5820 }
5821 }
5822 if (indx >= numChans)
5823 {
5824 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
5825 __func__, channelNum);
5826 return -EINVAL;
5827 }
5828 /* Set the Operational Channel */
5829 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
5830 channelNum);
5831 pRoamProfile->ChannelInfo.numOfChannels = 1;
5832 pHddStaCtx->conn_info.operationChannel = channelNum;
5833 pRoamProfile->ChannelInfo.ChannelList =
5834 &pHddStaCtx->conn_info.operationChannel;
5835 }
5836 else
5837 {
5838 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5839 __func__, channelNum);
5840 return -EINVAL;
5841 }
5842 }
5843
5844 /* Initialize security parameters */
5845 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5846 if (status < 0)
5847 {
5848 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5849 __func__);
5850 return status;
5851 }
5852
5853 /* Issue connect start */
5854 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005855 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005856
5857 if (0 > status)
5858 {
5859 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5860 return status;
5861 }
5862
5863 return 0;
5864}
5865
5866/*
5867 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5868 * This function is used to leave an IBSS
5869 */
5870static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5871 struct net_device *dev
5872 )
5873{
5874 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5875 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5876 tCsrRoamProfile *pRoamProfile;
5877
5878 ENTER();
5879
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005880 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5881 {
5882 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5883 "%s:LOGP in Progress. Ignore!!!", __func__);
5884 return -EAGAIN;
5885 }
5886
Jeff Johnson295189b2012-06-20 16:38:30 -07005887 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5888 if (NULL == pWextState)
5889 {
5890 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5891 __func__);
5892 return -EIO;
5893 }
5894
5895 pRoamProfile = &pWextState->roamProfile;
5896
5897 /* Issue disconnect only if interface type is set to IBSS */
5898 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5899 {
5900 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5901 __func__);
5902 return -EINVAL;
5903 }
5904
5905 /* Issue Disconnect request */
5906 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5907 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5908 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5909
5910 return 0;
5911}
5912
5913/*
5914 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5915 * This function is used to set the phy parameters
5916 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5917 */
5918static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5919 u32 changed)
5920{
5921 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5922 tHalHandle hHal = pHddCtx->hHal;
5923
5924 ENTER();
5925
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005926 if ( pHddCtx->isLogpInProgress )
5927 {
5928 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5929 "%s:LOGP in Progress. Ignore!!!", __func__);
5930 return -EAGAIN;
5931 }
5932
Jeff Johnson295189b2012-06-20 16:38:30 -07005933 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
5934 {
5935 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
5936 WNI_CFG_RTS_THRESHOLD_STAMAX :
5937 wiphy->rts_threshold;
5938
5939 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
5940 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
5941 {
5942 hddLog(VOS_TRACE_LEVEL_ERROR,
5943 "%s: Invalid RTS Threshold value %hu",
5944 __func__, rts_threshold);
5945 return -EINVAL;
5946 }
5947
5948 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
5949 rts_threshold, ccmCfgSetCallback,
5950 eANI_BOOLEAN_TRUE))
5951 {
5952 hddLog(VOS_TRACE_LEVEL_ERROR,
5953 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
5954 __func__, rts_threshold);
5955 return -EIO;
5956 }
5957
5958 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
5959 rts_threshold);
5960 }
5961
5962 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
5963 {
5964 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
5965 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
5966 wiphy->frag_threshold;
5967
5968 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
5969 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
5970 {
5971 hddLog(VOS_TRACE_LEVEL_ERROR,
5972 "%s: Invalid frag_threshold value %hu", __func__,
5973 frag_threshold);
5974 return -EINVAL;
5975 }
5976
5977 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
5978 frag_threshold, ccmCfgSetCallback,
5979 eANI_BOOLEAN_TRUE))
5980 {
5981 hddLog(VOS_TRACE_LEVEL_ERROR,
5982 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
5983 __func__, frag_threshold);
5984 return -EIO;
5985 }
5986
5987 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
5988 frag_threshold);
5989 }
5990
5991 if ((changed & WIPHY_PARAM_RETRY_SHORT)
5992 || (changed & WIPHY_PARAM_RETRY_LONG))
5993 {
5994 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
5995 wiphy->retry_short :
5996 wiphy->retry_long;
5997
5998 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
5999 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
6000 {
6001 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
6002 __func__, retry_value);
6003 return -EINVAL;
6004 }
6005
6006 if (changed & WIPHY_PARAM_RETRY_SHORT)
6007 {
6008 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
6009 retry_value, ccmCfgSetCallback,
6010 eANI_BOOLEAN_TRUE))
6011 {
6012 hddLog(VOS_TRACE_LEVEL_ERROR,
6013 "%s: ccmCfgSetInt failed for long retry count %hu",
6014 __func__, retry_value);
6015 return -EIO;
6016 }
6017 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
6018 __func__, retry_value);
6019 }
6020 else if (changed & WIPHY_PARAM_RETRY_SHORT)
6021 {
6022 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
6023 retry_value, ccmCfgSetCallback,
6024 eANI_BOOLEAN_TRUE))
6025 {
6026 hddLog(VOS_TRACE_LEVEL_ERROR,
6027 "%s: ccmCfgSetInt failed for short retry count %hu",
6028 __func__, retry_value);
6029 return -EIO;
6030 }
6031 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
6032 __func__, retry_value);
6033 }
6034 }
6035
6036 return 0;
6037}
6038
6039/*
6040 * FUNCTION: wlan_hdd_cfg80211_set_txpower
6041 * This function is used to set the txpower
6042 */
6043static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
6044#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
6045 enum tx_power_setting type,
6046#else
6047 enum nl80211_tx_power_setting type,
6048#endif
6049 int dbm)
6050{
6051 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6052 tHalHandle hHal = pHddCtx->hHal;
6053 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
6054 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
6055
6056 ENTER();
6057
6058 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
6059 dbm, ccmCfgSetCallback,
6060 eANI_BOOLEAN_TRUE))
6061 {
6062 hddLog(VOS_TRACE_LEVEL_ERROR,
6063 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
6064 return -EIO;
6065 }
6066
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006067 if ( pHddCtx->isLogpInProgress )
6068 {
6069 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6070 "%s:LOGP in Progress. Ignore!!!", __func__);
6071 return -EAGAIN;
6072 }
6073
Jeff Johnson295189b2012-06-20 16:38:30 -07006074 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
6075 dbm);
6076
6077 switch(type)
6078 {
6079 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
6080 /* Fall through */
6081 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
6082 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
6083 {
6084 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
6085 __func__);
6086 return -EIO;
6087 }
6088 break;
6089 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
6090 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
6091 __func__);
6092 return -EOPNOTSUPP;
6093 break;
6094 default:
6095 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
6096 __func__, type);
6097 return -EIO;
6098 }
6099
6100 return 0;
6101}
6102
6103/*
6104 * FUNCTION: wlan_hdd_cfg80211_get_txpower
6105 * This function is used to read the txpower
6106 */
6107static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
6108{
6109
6110 hdd_adapter_t *pAdapter;
6111 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6112
Jeff Johnsone7245742012-09-05 17:12:55 -07006113 ENTER();
6114
Jeff Johnson295189b2012-06-20 16:38:30 -07006115 if (NULL == pHddCtx)
6116 {
6117 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
6118 *dbm = 0;
6119 return -ENOENT;
6120 }
6121
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006122 if ( pHddCtx->isLogpInProgress )
6123 {
6124 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6125 "%s:LOGP in Progress. Ignore!!!", __func__);
6126 return -EAGAIN;
6127 }
6128
Jeff Johnson295189b2012-06-20 16:38:30 -07006129 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
6130 if (NULL == pAdapter)
6131 {
6132 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
6133 return -ENOENT;
6134 }
6135
6136 wlan_hdd_get_classAstats(pAdapter);
6137 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
6138
Jeff Johnsone7245742012-09-05 17:12:55 -07006139 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006140 return 0;
6141}
6142
6143static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
6144 u8* mac, struct station_info *sinfo)
6145{
6146 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
6147 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6148 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
6149 tANI_U8 rate_flags;
6150
6151 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6152 hdd_config_t *pCfg = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07006153
6154 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
6155 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
6156 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
6157 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
6158 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
6159 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
6160 tANI_U16 maxRate = 0;
6161 tANI_U16 myRate;
6162 tANI_U16 currentRate = 0;
6163 tANI_U8 maxSpeedMCS = 0;
6164 tANI_U8 maxMCSIdx = 0;
6165 tANI_U8 rateFlag = 1;
6166 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006167 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07006168
Jeff Johnsone7245742012-09-05 17:12:55 -07006169 ENTER();
6170
Jeff Johnson295189b2012-06-20 16:38:30 -07006171 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
6172 (0 == ssidlen))
6173 {
6174 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
6175 " Invalid ssidlen, %d", __func__, ssidlen);
6176 /*To keep GUI happy*/
6177 return 0;
6178 }
6179
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006180 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6181 {
6182 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6183 "%s:LOGP in Progress. Ignore!!!", __func__);
6184 return -EAGAIN;
6185 }
6186
Jeff Johnson295189b2012-06-20 16:38:30 -07006187 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
6188 sinfo->filled |= STATION_INFO_SIGNAL;
6189
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006190 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006191 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
6192
6193 //convert to the UI units of 100kbps
6194 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
6195
6196#ifdef LINKSPEED_DEBUG_ENABLED
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006197 pr_info("RSSI %d, RLMS %u, rate %d, rssi high %d, rssi mid %d, rssi low %d, rate_flags 0x%x\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07006198 sinfo->signal,
6199 pCfg->reportMaxLinkSpeed,
6200 myRate,
6201 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006202 (int) pCfg->linkSpeedRssiMid,
6203 (int) pCfg->linkSpeedRssiLow,
6204 (int) rate_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07006205#endif //LINKSPEED_DEBUG_ENABLED
6206
6207 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
6208 {
6209 // we do not want to necessarily report the current speed
6210 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
6211 {
6212 // report the max possible speed
6213 rssidx = 0;
6214 }
6215 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
6216 {
6217 // report the max possible speed with RSSI scaling
6218 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
6219 {
6220 // report the max possible speed
6221 rssidx = 0;
6222 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006223 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07006224 {
6225 // report middle speed
6226 rssidx = 1;
6227 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006228 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
6229 {
6230 // report middle speed
6231 rssidx = 2;
6232 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006233 else
6234 {
6235 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006236 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07006237 }
6238 }
6239 else
6240 {
6241 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
6242 hddLog(VOS_TRACE_LEVEL_ERROR,
6243 "%s: Invalid value for reportMaxLinkSpeed: %u",
6244 __func__, pCfg->reportMaxLinkSpeed);
6245 rssidx = 0;
6246 }
6247
6248 maxRate = 0;
6249
6250 /* Get Basic Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306251 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_OPERATIONAL_RATE_SET,
6252 OperationalRates, &ORLeng))
6253 {
6254 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6255 /*To keep GUI happy*/
6256 return 0;
6257 }
6258
Jeff Johnson295189b2012-06-20 16:38:30 -07006259 for (i = 0; i < ORLeng; i++)
6260 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006261 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006262 {
6263 /* Validate Rate Set */
6264 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
6265 {
6266 currentRate = supported_data_rate[j].supported_rate[rssidx];
6267 break;
6268 }
6269 }
6270 /* Update MAX rate */
6271 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6272 }
6273
6274 /* Get Extended Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306275 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
6276 ExtendedRates, &ERLeng))
6277 {
6278 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6279 /*To keep GUI happy*/
6280 return 0;
6281 }
6282
Jeff Johnson295189b2012-06-20 16:38:30 -07006283 for (i = 0; i < ERLeng; i++)
6284 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006285 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006286 {
6287 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
6288 {
6289 currentRate = supported_data_rate[j].supported_rate[rssidx];
6290 break;
6291 }
6292 }
6293 /* Update MAX rate */
6294 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6295 }
6296
6297 /* Get MCS Rate Set -- but only if we are connected at MCS
6298 rates or if we are always reporting max speed or if we have
6299 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006300 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07006301 {
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306302 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_CURRENT_MCS_SET,
6303 MCSRates, &MCSLeng))
6304 {
6305 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6306 /*To keep GUI happy*/
6307 return 0;
6308 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006309 rateFlag = 0;
6310 if (rate_flags & eHAL_TX_RATE_HT40)
6311 {
6312 rateFlag |= 1;
6313 }
6314 if (rate_flags & eHAL_TX_RATE_SGI)
6315 {
6316 rateFlag |= 2;
6317 }
6318
6319 for (i = 0; i < MCSLeng; i++)
6320 {
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006321 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
6322 for (j = 0; j < temp; j++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006323 {
6324 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
6325 {
6326 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
6327 break;
6328 }
6329 }
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006330 if ((j < temp) && (currentRate > maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006331 {
6332 maxRate = currentRate;
6333 maxSpeedMCS = 1;
6334 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
6335 }
6336 }
6337 }
6338
6339 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006340 if (((maxRate < myRate) && (0 == rssidx)) ||
6341 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006342 {
6343 maxRate = myRate;
6344 if (rate_flags & eHAL_TX_RATE_LEGACY)
6345 {
6346 maxSpeedMCS = 0;
6347 }
6348 else
6349 {
6350 maxSpeedMCS = 1;
6351 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6352 }
6353 }
6354
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006355 if ((!maxSpeedMCS) || (0 != rssidx))
Jeff Johnson295189b2012-06-20 16:38:30 -07006356 {
6357 sinfo->txrate.legacy = maxRate;
6358#ifdef LINKSPEED_DEBUG_ENABLED
6359 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
6360#endif //LINKSPEED_DEBUG_ENABLED
6361 }
6362 else
6363 {
6364 sinfo->txrate.mcs = maxMCSIdx;
6365 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6366 if (rate_flags & eHAL_TX_RATE_SGI)
6367 {
6368 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6369 }
6370 if (rate_flags & eHAL_TX_RATE_HT40)
6371 {
6372 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6373 }
6374#ifdef LINKSPEED_DEBUG_ENABLED
6375 pr_info("Reporting MCS rate %d flags %x\n",
6376 sinfo->txrate.mcs,
6377 sinfo->txrate.flags );
6378#endif //LINKSPEED_DEBUG_ENABLED
6379 }
6380 }
6381 else
6382 {
6383 // report current rate instead of max rate
6384
6385 if (rate_flags & eHAL_TX_RATE_LEGACY)
6386 {
6387 //provide to the UI in units of 100kbps
6388 sinfo->txrate.legacy = myRate;
6389#ifdef LINKSPEED_DEBUG_ENABLED
6390 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
6391#endif //LINKSPEED_DEBUG_ENABLED
6392 }
6393 else
6394 {
6395 //must be MCS
6396 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6397 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6398 if (rate_flags & eHAL_TX_RATE_SGI)
6399 {
6400 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6401 }
6402 if (rate_flags & eHAL_TX_RATE_HT40)
6403 {
6404 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6405 }
6406#ifdef LINKSPEED_DEBUG_ENABLED
6407 pr_info("Reporting actual MCS rate %d flags %x\n",
6408 sinfo->txrate.mcs,
6409 sinfo->txrate.flags );
6410#endif //LINKSPEED_DEBUG_ENABLED
6411 }
6412 }
6413 sinfo->filled |= STATION_INFO_TX_BITRATE;
6414
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006415 sinfo->tx_packets =
6416 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
6417 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
6418 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
6419 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
6420
6421 sinfo->tx_retries =
6422 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
6423 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
6424 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
6425 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
6426
6427 sinfo->tx_failed =
6428 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
6429 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
6430 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
6431 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
6432
6433 sinfo->filled |=
6434 STATION_INFO_TX_PACKETS |
6435 STATION_INFO_TX_RETRIES |
6436 STATION_INFO_TX_FAILED;
6437
6438 EXIT();
6439 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006440}
6441
6442static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
6443 struct net_device *dev, bool mode, v_SINT_t timeout)
6444{
6445 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6446 VOS_STATUS vos_status;
6447
Jeff Johnsone7245742012-09-05 17:12:55 -07006448 ENTER();
6449
Jeff Johnson295189b2012-06-20 16:38:30 -07006450 if (NULL == pAdapter)
6451 {
6452 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6453 return -ENODEV;
6454 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006455 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6456 {
6457 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6458 "%s:LOGP in Progress. Ignore!!!", __func__);
6459 return -EAGAIN;
6460 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006461
6462 /**The get power cmd from the supplicant gets updated by the nl only
6463 *on successful execution of the function call
6464 *we are oppositely mapped w.r.t mode in the driver
6465 **/
6466 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
6467
Jeff Johnsone7245742012-09-05 17:12:55 -07006468 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006469 if (VOS_STATUS_E_FAILURE == vos_status)
6470 {
6471 return -EINVAL;
6472 }
6473 return 0;
6474}
6475
6476
6477#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6478static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
6479 struct net_device *netdev,
6480 u8 key_index)
6481{
Jeff Johnsone7245742012-09-05 17:12:55 -07006482 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006483 return 0;
6484}
6485#endif //LINUX_VERSION_CODE
6486
6487#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
6488static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6489 struct net_device *dev,
6490 struct ieee80211_txq_params *params)
6491{
Jeff Johnsone7245742012-09-05 17:12:55 -07006492 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006493 return 0;
6494}
6495#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6496static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6497 struct ieee80211_txq_params *params)
6498{
Jeff Johnsone7245742012-09-05 17:12:55 -07006499 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006500 return 0;
6501}
6502#endif //LINUX_VERSION_CODE
6503
6504static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
6505 struct net_device *dev, u8 *mac)
6506{
6507 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006508 VOS_STATUS vos_status;
6509 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006510
Jeff Johnsone7245742012-09-05 17:12:55 -07006511 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006512 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6513 {
6514 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6515 return -EINVAL;
6516 }
6517
6518 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6519 {
6520 hddLog( LOGE,
6521 "%s: Wlan Load/Unload is in progress", __func__);
6522 return -EBUSY;
6523 }
6524
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006525 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6526 {
6527 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6528 "%s:LOGP in Progress. Ignore!!!", __func__);
6529 return -EAGAIN;
6530 }
6531
Jeff Johnson295189b2012-06-20 16:38:30 -07006532 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006533 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006534 )
6535 {
6536 if( NULL == mac )
6537 {
6538 v_U16_t i;
6539 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
6540 {
6541 if(pAdapter->aStaInfo[i].isUsed)
6542 {
6543 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
6544 hddLog(VOS_TRACE_LEVEL_INFO,
6545 "%s: Delete STA with MAC::"
6546 "%02x:%02x:%02x:%02x:%02x:%02x",
6547 __func__,
6548 macAddr[0], macAddr[1], macAddr[2],
6549 macAddr[3], macAddr[4], macAddr[5]);
6550 hdd_softap_sta_deauth(pAdapter, macAddr);
6551 }
6552 }
6553 }
6554 else
6555 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006556
6557 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
6558 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6559 {
6560 hddLog(VOS_TRACE_LEVEL_INFO,
6561 "%s: Skip this DEL STA as this is not used::"
6562 "%02x:%02x:%02x:%02x:%02x:%02x",
6563 __func__,
6564 mac[0], mac[1], mac[2],
6565 mac[3], mac[4], mac[5]);
6566 return -ENOENT;
6567 }
6568
6569 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
6570 {
6571 hddLog(VOS_TRACE_LEVEL_INFO,
6572 "%s: Skip this DEL STA as deauth is in progress::"
6573 "%02x:%02x:%02x:%02x:%02x:%02x",
6574 __func__,
6575 mac[0], mac[1], mac[2],
6576 mac[3], mac[4], mac[5]);
6577 return -ENOENT;
6578 }
6579
6580 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
6581
Jeff Johnson295189b2012-06-20 16:38:30 -07006582 hddLog(VOS_TRACE_LEVEL_INFO,
6583 "%s: Delete STA with MAC::"
6584 "%02x:%02x:%02x:%02x:%02x:%02x",
6585 __func__,
6586 mac[0], mac[1], mac[2],
6587 mac[3], mac[4], mac[5]);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006588
6589 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
6590 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6591 {
6592 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
6593 hddLog(VOS_TRACE_LEVEL_INFO,
6594 "%s: STA removal failed for ::"
6595 "%02x:%02x:%02x:%02x:%02x:%02x",
6596 __func__,
6597 mac[0], mac[1], mac[2],
6598 mac[3], mac[4], mac[5]);
6599 return -ENOENT;
6600 }
6601
Jeff Johnson295189b2012-06-20 16:38:30 -07006602 }
6603 }
6604
6605 EXIT();
6606
6607 return 0;
6608}
6609
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006610static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
6611 struct net_device *dev, u8 *mac, struct station_parameters *params)
6612{
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006613 int status = -EPERM;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006614#ifdef FEATURE_WLAN_TDLS
6615 u32 mask, set;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006616 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006617 mask = params->sta_flags_mask;
6618
6619 set = params->sta_flags_set;
6620
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006621#ifdef WLAN_FEATURE_TDLS_DEBUG
6622 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6623 "%s: mask 0x%x set 0x%x " MAC_ADDRESS_STR,
6624 __func__, mask, set, MAC_ADDR_ARRAY(mac));
6625#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006626
6627 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6628 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006629 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006630 }
6631 }
6632#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006633 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006634}
6635
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006636
6637#ifdef FEATURE_WLAN_LFR
6638static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006639 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006640{
6641#define MAX_PMKSAIDS_IN_CACHE 8
6642 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -07006643 static tANI_U32 i; // HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006644 tANI_U32 j=0;
6645 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6646 tHalHandle halHandle;
6647 eHalStatus result;
6648 tANI_U8 BSSIDMatched = 0;
6649
Jeff Johnsone7245742012-09-05 17:12:55 -07006650 ENTER();
6651
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006652 // Validate pAdapter
6653 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6654 {
6655 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6656 return -EINVAL;
6657 }
6658
6659 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6660 {
6661 hddLog( LOGE,
6662 "%s: Wlan Load/Unload is in progress", __func__);
6663 return -EBUSY;
6664 }
6665
6666 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6667 {
6668 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6669 "%s:LOGP in Progress. Ignore!!!", __func__);
6670 return -EAGAIN;
6671 }
6672
6673 // Retrieve halHandle
6674 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
6675
6676 for (j = 0; j < i; j++)
6677 {
6678 if(vos_mem_compare(PMKIDCache[j].BSSID,
6679 pmksa->bssid, WNI_CFG_BSSID_LEN))
6680 {
6681 /* BSSID matched previous entry. Overwrite it. */
6682 BSSIDMatched = 1;
6683 vos_mem_copy(PMKIDCache[j].BSSID,
6684 pmksa->bssid, WNI_CFG_BSSID_LEN);
6685 vos_mem_copy(PMKIDCache[j].PMKID,
6686 pmksa->pmkid,
6687 CSR_RSN_PMKID_SIZE);
6688 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006689 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006690 dump_bssid(pmksa->bssid);
6691 dump_pmkid(halHandle, pmksa->pmkid);
6692 break;
6693 }
6694 }
6695
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07006696 /* Check we compared all entries,if then take the first slot now */
6697 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
6698
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006699 if (!BSSIDMatched)
6700 {
6701 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
6702 vos_mem_copy(PMKIDCache[i].BSSID,
6703 pmksa->bssid, ETHER_ADDR_LEN);
6704 vos_mem_copy(PMKIDCache[i].PMKID,
6705 pmksa->pmkid,
6706 CSR_RSN_PMKID_SIZE);
6707 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006708 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006709 dump_bssid(pmksa->bssid);
6710 dump_pmkid(halHandle, pmksa->pmkid);
6711 // Increment the HDD Local Cache index
6712 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
6713 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
6714 }
6715
6716
6717 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
6718 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006719 // __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006720 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006721 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006722 // Finally set the PMKSA ID Cache in CSR
6723 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
6724 PMKIDCache,
6725 i );
6726 return 0;
6727}
6728
6729
6730static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006731 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006732{
Jeff Johnsone7245742012-09-05 17:12:55 -07006733 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006734 // TODO: Implement this later.
6735 return 0;
6736}
6737
6738static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
6739{
Jeff Johnsone7245742012-09-05 17:12:55 -07006740 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006741 // TODO: Implement this later.
6742 return 0;
6743}
6744#endif
6745
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006746#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6747static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
6748 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
6749{
6750 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6751 hdd_station_ctx_t *pHddStaCtx;
6752
6753 if (NULL == pAdapter)
6754 {
6755 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6756 return -ENODEV;
6757 }
6758
6759 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6760
6761 // Added for debug on reception of Re-assoc Req.
6762 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6763 {
6764 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
6765 ftie->ie_len);
6766 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
6767 }
6768
6769#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
6770 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
6771 ftie->ie_len);
6772#endif
6773
6774 // Pass the received FT IEs to SME
Gopichand Nakkala356fb102013-03-06 12:34:04 +05306775 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6776 (const u8 *)ftie->ie,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006777 ftie->ie_len);
6778 return 0;
6779}
6780#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006781
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006782#ifdef FEATURE_WLAN_TDLS
6783static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
6784 u8 *peer, u8 action_code, u8 dialog_token,
6785 u16 status_code, const u8 *buf, size_t len)
6786{
6787
6788 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6789 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006790 u8 peerMac[6];
6791 VOS_STATUS status;
Gopichand Nakkala05922802013-03-14 12:23:19 -07006792 int max_sta_failed = 0;
Hoonki Leea34dd892013-02-05 22:56:02 -08006793 int responder;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006794
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006795 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006796 {
6797 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6798 "Invalid arguments");
6799 return -EINVAL;
6800 }
6801
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006802 if (pHddCtx->isLogpInProgress)
6803 {
6804 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6805 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006806 wlan_hdd_tdls_set_link_status(pAdapter, peer, eTDLS_LINK_IDLE);
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006807 return -EBUSY;
6808 }
6809
Hoonki Lee27511902013-03-14 18:19:06 -07006810 if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006811 {
Hoonki Lee27511902013-03-14 18:19:06 -07006812 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6813 "%s: TDLS mode is disabled OR not enabled in FW."
6814 MAC_ADDRESS_STR " action %d declined.",
6815 __func__, MAC_ADDR_ARRAY(peer), action_code);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006816 return -ENOTSUPP;
6817 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006818
Hoonki Lee27511902013-03-14 18:19:06 -07006819 if ((SIR_MAC_TDLS_SETUP_RSP == action_code) ||
6820 (SIR_MAC_TDLS_DIS_RSP == action_code))
6821 {
6822 wlan_hdd_tdls_set_cap (pAdapter, peerMac, eTDLS_CAP_SUPPORTED);
6823 }
6824
6825 /* other than teardown frame, other mgmt frames are not sent if disabled */
6826 if (SIR_MAC_TDLS_TEARDOWN != action_code)
6827 {
6828 /* if tdls_mode is disabled to respond to peer's request */
6829 if (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode)
6830 {
6831 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6832 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006833 " TDLS mode is disabled. action %d declined.",
6834 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee27511902013-03-14 18:19:06 -07006835
6836 return -ENOTSUPP;
6837 }
6838 }
6839
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006840 if (WLAN_IS_TDLS_SETUP_ACTION(action_code))
6841 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006842 if (wlan_hdd_tdls_is_progress(pAdapter, peer, TRUE))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006843 {
6844 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006845 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006846 " TDLS setup is ongoing. action %d declined.",
6847 __func__, MAC_ADDR_ARRAY(peer), action_code);
6848 return -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006849 }
6850 }
6851
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006852 if (SIR_MAC_TDLS_SETUP_REQ == action_code ||
6853 SIR_MAC_TDLS_SETUP_RSP == action_code )
Lee Hoonkic1262f22013-01-24 21:59:00 -08006854 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006855 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
Lee Hoonkic1262f22013-01-24 21:59:00 -08006856 {
6857 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
6858 we return error code at 'add_station()'. Hence we have this
6859 check again in addtion to add_station().
6860 Anyway, there is no hard to double-check. */
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006861 if (SIR_MAC_TDLS_SETUP_REQ == action_code)
Lee Hoonkic1262f22013-01-24 21:59:00 -08006862 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006863 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6864 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006865 " TDLS Max peer already connected. action %d declined.",
6866 __func__, MAC_ADDR_ARRAY(peer), action_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006867 goto error;
Lee Hoonkic1262f22013-01-24 21:59:00 -08006868 }
6869 else
6870 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006871 /* maximum reached. tweak to send error code to peer and return
6872 error code to supplicant */
Lee Hoonkic1262f22013-01-24 21:59:00 -08006873 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006874 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6875 "%s: " MAC_ADDRESS_STR
6876 " TDLS Max peer already connected send response status %d",
6877 __func__, MAC_ADDR_ARRAY(peer), status_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006878 max_sta_failed = -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006879 /* fall through to send setup resp with failure status
6880 code */
Lee Hoonkic1262f22013-01-24 21:59:00 -08006881 }
6882 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006883 else
6884 {
6885 hddTdlsPeer_t *pTdlsPeer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006886 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006887 if (pTdlsPeer && (eTDLS_LINK_CONNECTED == pTdlsPeer->link_status))
6888 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006889 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006890 "%s:" MAC_ADDRESS_STR " already connected. action %d declined.",
6891 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006892 return -EPERM;
6893 }
6894 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006895 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006896 vos_mem_copy(peerMac, peer, 6);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006897
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006898#ifdef WLAN_FEATURE_TDLS_DEBUG
6899 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006900 "%s: " MAC_ADDRESS_STR " action %d, dialog_token %d status %d, len = %d",
6901 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
6902 action_code, dialog_token, status_code, len);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006903#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006904
Hoonki Leea34dd892013-02-05 22:56:02 -08006905 /*Except teardown responder will not be used so just make 0*/
6906 responder = 0;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006907 if (SIR_MAC_TDLS_TEARDOWN == action_code)
Hoonki Leea34dd892013-02-05 22:56:02 -08006908 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006909 responder = wlan_hdd_tdls_get_responder(pAdapter, peerMac);
6910 if(-1 == responder)
Hoonki Leea34dd892013-02-05 22:56:02 -08006911 {
6912 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006913 "%s: " MAC_ADDRESS_STR " peer doesn't exist dialog_token %d status %d, len = %d",
6914 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
Hoonki Leea34dd892013-02-05 22:56:02 -08006915 dialog_token, status_code, len);
6916 return -EPERM;
6917 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006918 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006919
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006920 INIT_COMPLETION(pAdapter->tdls_mgmt_comp);
6921
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006922 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
Hoonki Leea34dd892013-02-05 22:56:02 -08006923 peerMac, action_code, dialog_token, status_code, (tANI_U8 *)buf, len, responder);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006924
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006925 if (VOS_STATUS_SUCCESS != status)
6926 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006927 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6928 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006929 return -EPERM;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006930 }
6931
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006932 /* not block discovery request, as it is called from timer callback */
6933 if (SIR_MAC_TDLS_DIS_REQ != action_code)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006934 {
Pervinder Singhb4638422013-03-04 22:51:36 -08006935 long rc;
6936
6937 rc = wait_for_completion_interruptible_timeout(&pAdapter->tdls_mgmt_comp,
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006938 msecs_to_jiffies(WAIT_TIME_TDLS_MGMT));
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006939
Pervinder Singhb4638422013-03-04 22:51:36 -08006940 if ((rc <= 0) || (TRUE != pAdapter->mgmtTxCompletionStatus))
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006941 {
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006942 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pervinder Singhb4638422013-03-04 22:51:36 -08006943 "%s: Mgmt Tx Completion failed status %ld TxCompletion %lu",
6944 __func__, rc, pAdapter->mgmtTxCompletionStatus);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006945 return -EPERM;
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006946 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006947 }
6948
Gopichand Nakkala05922802013-03-14 12:23:19 -07006949 if (max_sta_failed)
6950 return max_sta_failed;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006951
Hoonki Leea34dd892013-02-05 22:56:02 -08006952 if (SIR_MAC_TDLS_SETUP_RSP == action_code)
6953 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006954 wlan_hdd_tdls_set_responder(pAdapter, peerMac, TRUE);
Hoonki Leea34dd892013-02-05 22:56:02 -08006955 }
6956 else if (SIR_MAC_TDLS_SETUP_CNF == action_code)
6957 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006958 wlan_hdd_tdls_set_responder(pAdapter, peerMac, FALSE);
Hoonki Leea34dd892013-02-05 22:56:02 -08006959 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006960
6961 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07006962error:
6963 /* max_sta_failed ; we didn't set to CONNECTING for this case,
6964 because we already know that this transaction will be failed,
6965 but we weren't sure if supplicant call DISABLE_LINK or not. So,
6966 to be safe, do not change the state mahine.
6967 */
6968 if(max_sta_failed == 0 &&
6969 (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
6970 wlan_hdd_tdls_set_link_status(pAdapter, peerMac, eTDLS_LINK_IDLE);
6971 return -EPERM;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006972}
6973
6974static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
6975 u8 *peer, enum nl80211_tdls_operation oper)
6976{
6977 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6978 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006979#ifdef WLAN_FEATURE_TDLS_DEBUG
6980 const char *tdls_oper_str[]= {
6981 "NL80211_TDLS_DISCOVERY_REQ",
6982 "NL80211_TDLS_SETUP",
6983 "NL80211_TDLS_TEARDOWN",
6984 "NL80211_TDLS_ENABLE_LINK",
6985 "NL80211_TDLS_DISABLE_LINK",
6986 "NL80211_TDLS_UNKONW_OPER"};
6987#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006988
6989 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6990 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006991 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006992 "Invalid arguments");
6993 return -EINVAL;
6994 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006995
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006996 if (pHddCtx->isLogpInProgress)
6997 {
6998 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6999 "%s:LOGP in Progress. Ignore!!!", __func__);
7000 return -EBUSY;
7001 }
7002
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007003#ifdef WLAN_FEATURE_TDLS_DEBUG
7004 if((int)oper > 4)
7005 oper = 5;
7006
7007 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007008 "%s: " MAC_ADDRESS_STR " %d (%s) ", "tdls_oper",
7009 MAC_ADDR_ARRAY(peer), (int)oper,
7010 tdls_oper_str[(int)oper]);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007011#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007012
7013 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007014 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007015 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007016 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007017 "TDLS Disabled in INI OR not enabled in FW.\
7018 Cannot process TDLS commands \n");
7019 return -ENOTSUPP;
7020 }
7021
7022 switch (oper) {
7023 case NL80211_TDLS_ENABLE_LINK:
7024 {
Hoonki Lee387663d2013-02-05 18:08:43 -08007025 hddTdlsPeer_t *pTdlsPeer;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007026 VOS_STATUS status;
7027
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007028 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007029
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007030 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
7031 "%s: TDLS_LINK_ENABLE " MAC_ADDRESS_STR,
7032 __func__, MAC_ADDR_ARRAY(peer));
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007033
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007034 if ( NULL == pTdlsPeer ) {
7035 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_hdd_tdls_find_peer "
7036 MAC_ADDRESS_STR " failed",
7037 __func__, MAC_ADDR_ARRAY(peer));
7038 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007039 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007040
7041 if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status)
7042 {
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007043 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007044 /* start TDLS client registration with TL */
7045 status = hdd_roamRegisterTDLSSTA( pAdapter, peer, pTdlsPeer->staId, pTdlsPeer->signature);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007046 if (VOS_STATUS_SUCCESS == status)
7047 {
7048 wlan_hdd_tdls_increment_peer_count(pAdapter);
7049 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007050 wlan_hdd_tdls_check_bmps(pAdapter);
7051 }
7052
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007053 }
7054 break;
7055 case NL80211_TDLS_DISABLE_LINK:
Lee Hoonkic1262f22013-01-24 21:59:00 -08007056 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007057 hddTdlsPeer_t *curr_peer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007058
7059 if(NULL != curr_peer)
Lee Hoonkic1262f22013-01-24 21:59:00 -08007060 {
7061 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
7062 pAdapter->sessionId, peer );
Gopichand Nakkala8b00c632013-03-08 19:47:52 -08007063 wlan_hdd_tdls_set_peer_link_status(curr_peer, eTDLS_LINK_IDLE);
Lee Hoonkic1262f22013-01-24 21:59:00 -08007064 }
7065 else
7066 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007067 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7068 "%s: TDLS Peer Station doesn't exist.", __func__);
Lee Hoonkic1262f22013-01-24 21:59:00 -08007069 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08007070 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007071 break;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007072 case NL80211_TDLS_TEARDOWN:
7073 case NL80211_TDLS_SETUP:
7074 case NL80211_TDLS_DISCOVERY_REQ:
7075 /* We don't support in-driver setup/teardown/discovery */
7076 return -ENOTSUPP;
7077 default:
7078 return -ENOTSUPP;
7079 }
7080 return 0;
7081}
Chilam NG571c65a2013-01-19 12:27:36 +05307082
7083int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
7084 struct net_device *dev, u8 *peer)
7085{
7086 hddLog(VOS_TRACE_LEVEL_INFO, "tdls send discover req: %x %x %x %x %x %x",
7087 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5]);
7088
7089 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
7090 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
7091}
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007092#endif
7093
Jeff Johnson295189b2012-06-20 16:38:30 -07007094/* cfg80211_ops */
7095static struct cfg80211_ops wlan_hdd_cfg80211_ops =
7096{
7097 .add_virtual_intf = wlan_hdd_add_virtual_intf,
7098 .del_virtual_intf = wlan_hdd_del_virtual_intf,
7099 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
7100 .change_station = wlan_hdd_change_station,
7101#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
7102 .add_beacon = wlan_hdd_cfg80211_add_beacon,
7103 .del_beacon = wlan_hdd_cfg80211_del_beacon,
7104 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007105#else
7106 .start_ap = wlan_hdd_cfg80211_start_ap,
7107 .change_beacon = wlan_hdd_cfg80211_change_beacon,
7108 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07007109#endif
7110 .change_bss = wlan_hdd_cfg80211_change_bss,
7111 .add_key = wlan_hdd_cfg80211_add_key,
7112 .get_key = wlan_hdd_cfg80211_get_key,
7113 .del_key = wlan_hdd_cfg80211_del_key,
7114 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08007115#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07007116 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08007117#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007118 .scan = wlan_hdd_cfg80211_scan,
7119 .connect = wlan_hdd_cfg80211_connect,
7120 .disconnect = wlan_hdd_cfg80211_disconnect,
7121 .join_ibss = wlan_hdd_cfg80211_join_ibss,
7122 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
7123 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
7124 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
7125 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
Jeff Johnson295189b2012-06-20 16:38:30 -07007126 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
7127 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
7128 .mgmt_tx = wlan_hdd_action,
7129#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7130 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
7131 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
7132 .set_txq_params = wlan_hdd_set_txq_params,
7133#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007134 .get_station = wlan_hdd_cfg80211_get_station,
7135 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
7136 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007137 .add_station = wlan_hdd_cfg80211_add_station,
7138#ifdef FEATURE_WLAN_LFR
7139 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
7140 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
7141 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
7142#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007143#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
7144 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
7145#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007146#ifdef FEATURE_WLAN_TDLS
7147 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
7148 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
7149#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007150};
7151