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