blob: 8dbcdd49a6a01d87ea05122a1f9d834ea2442f95 [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"
Gopichand Nakkala20c4c042013-04-19 22:08:55 +053099#include "wlan_hdd_power.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700100#ifdef WLAN_BTAMP_FEATURE
101#include "bap_hdd_misc.h"
102#endif
103#include <qc_sap_ioctl.h>
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800104#ifdef FEATURE_WLAN_TDLS
105#include "wlan_hdd_tdls.h"
106#endif
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +0530107#include "wlan_nv.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700108
109#define g_mode_rates_size (12)
110#define a_mode_rates_size (8)
111#define FREQ_BASE_80211G (2407)
112#define FREQ_BAND_DIFF_80211G (5)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700113#define MAX_SCAN_SSID 9
Jeff Johnson295189b2012-06-20 16:38:30 -0700114#define GET_IE_LEN_IN_BSS_DESC(lenInBss) ( lenInBss + sizeof(lenInBss) - \
115 ((int) OFFSET_OF( tSirBssDescription, ieFields)))
116
117#define HDD2GHZCHAN(freq, chan, flag) { \
118 .band = IEEE80211_BAND_2GHZ, \
119 .center_freq = (freq), \
120 .hw_value = (chan),\
121 .flags = (flag), \
122 .max_antenna_gain = 0 ,\
123 .max_power = 30, \
124}
125
126#define HDD5GHZCHAN(freq, chan, flag) { \
127 .band = IEEE80211_BAND_5GHZ, \
128 .center_freq = (freq), \
129 .hw_value = (chan),\
130 .flags = (flag), \
131 .max_antenna_gain = 0 ,\
132 .max_power = 30, \
133}
134
135#define HDD_G_MODE_RATETAB(rate, rate_id, flag)\
136{\
137 .bitrate = rate, \
138 .hw_value = rate_id, \
139 .flags = flag, \
140}
141
Lee Hoonkic1262f22013-01-24 21:59:00 -0800142#ifndef WLAN_FEATURE_TDLS_DEBUG
143#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_INFO
144#else
145#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_ERROR
146#endif
147
Gopichand Nakkala356fb102013-03-06 12:34:04 +0530148#ifdef WLAN_FEATURE_VOWIFI_11R
149#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
150#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
151#endif
152
Jeff Johnson295189b2012-06-20 16:38:30 -0700153static const u32 hdd_cipher_suites[] =
154{
155 WLAN_CIPHER_SUITE_WEP40,
156 WLAN_CIPHER_SUITE_WEP104,
157 WLAN_CIPHER_SUITE_TKIP,
158#ifdef FEATURE_WLAN_CCX
159#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
160 WLAN_CIPHER_SUITE_KRK,
161 WLAN_CIPHER_SUITE_CCMP,
162#else
163 WLAN_CIPHER_SUITE_CCMP,
164#endif
165#ifdef FEATURE_WLAN_WAPI
166 WLAN_CIPHER_SUITE_SMS4,
167#endif
Chet Lanctot186b5732013-03-18 10:26:30 -0700168#ifdef WLAN_FEATURE_11W
169 WLAN_CIPHER_SUITE_AES_CMAC,
170#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700171};
172
173static inline int is_broadcast_ether_addr(const u8 *addr)
174{
175 return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&
176 (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
177}
178
179static struct ieee80211_channel hdd_channels_2_4_GHZ[] =
180{
181 HDD2GHZCHAN(2412, 1, 0) ,
182 HDD2GHZCHAN(2417, 2, 0) ,
183 HDD2GHZCHAN(2422, 3, 0) ,
184 HDD2GHZCHAN(2427, 4, 0) ,
185 HDD2GHZCHAN(2432, 5, 0) ,
186 HDD2GHZCHAN(2437, 6, 0) ,
187 HDD2GHZCHAN(2442, 7, 0) ,
188 HDD2GHZCHAN(2447, 8, 0) ,
189 HDD2GHZCHAN(2452, 9, 0) ,
190 HDD2GHZCHAN(2457, 10, 0) ,
191 HDD2GHZCHAN(2462, 11, 0) ,
192 HDD2GHZCHAN(2467, 12, 0) ,
193 HDD2GHZCHAN(2472, 13, 0) ,
194 HDD2GHZCHAN(2484, 14, 0) ,
195};
196
Jeff Johnson295189b2012-06-20 16:38:30 -0700197static struct ieee80211_channel hdd_social_channels_2_4_GHZ[] =
198{
199 HDD2GHZCHAN(2412, 1, 0) ,
200 HDD2GHZCHAN(2437, 6, 0) ,
201 HDD2GHZCHAN(2462, 11, 0) ,
202};
Jeff Johnson295189b2012-06-20 16:38:30 -0700203
204static struct ieee80211_channel hdd_channels_5_GHZ[] =
205{
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700206 HDD5GHZCHAN(4920, 240, 0) ,
207 HDD5GHZCHAN(4940, 244, 0) ,
208 HDD5GHZCHAN(4960, 248, 0) ,
209 HDD5GHZCHAN(4980, 252, 0) ,
210 HDD5GHZCHAN(5040, 208, 0) ,
211 HDD5GHZCHAN(5060, 212, 0) ,
212 HDD5GHZCHAN(5080, 216, 0) ,
Jeff Johnson295189b2012-06-20 16:38:30 -0700213 HDD5GHZCHAN(5180, 36, 0) ,
214 HDD5GHZCHAN(5200, 40, 0) ,
215 HDD5GHZCHAN(5220, 44, 0) ,
216 HDD5GHZCHAN(5240, 48, 0) ,
217 HDD5GHZCHAN(5260, 52, 0) ,
218 HDD5GHZCHAN(5280, 56, 0) ,
219 HDD5GHZCHAN(5300, 60, 0) ,
220 HDD5GHZCHAN(5320, 64, 0) ,
221 HDD5GHZCHAN(5500,100, 0) ,
222 HDD5GHZCHAN(5520,104, 0) ,
223 HDD5GHZCHAN(5540,108, 0) ,
224 HDD5GHZCHAN(5560,112, 0) ,
225 HDD5GHZCHAN(5580,116, 0) ,
226 HDD5GHZCHAN(5600,120, 0) ,
227 HDD5GHZCHAN(5620,124, 0) ,
228 HDD5GHZCHAN(5640,128, 0) ,
229 HDD5GHZCHAN(5660,132, 0) ,
230 HDD5GHZCHAN(5680,136, 0) ,
231 HDD5GHZCHAN(5700,140, 0) ,
232 HDD5GHZCHAN(5745,149, 0) ,
233 HDD5GHZCHAN(5765,153, 0) ,
234 HDD5GHZCHAN(5785,157, 0) ,
235 HDD5GHZCHAN(5805,161, 0) ,
236 HDD5GHZCHAN(5825,165, 0) ,
237};
238
239static struct ieee80211_rate g_mode_rates[] =
240{
241 HDD_G_MODE_RATETAB(10, 0x1, 0),
242 HDD_G_MODE_RATETAB(20, 0x2, 0),
243 HDD_G_MODE_RATETAB(55, 0x4, 0),
244 HDD_G_MODE_RATETAB(110, 0x8, 0),
245 HDD_G_MODE_RATETAB(60, 0x10, 0),
246 HDD_G_MODE_RATETAB(90, 0x20, 0),
247 HDD_G_MODE_RATETAB(120, 0x40, 0),
248 HDD_G_MODE_RATETAB(180, 0x80, 0),
249 HDD_G_MODE_RATETAB(240, 0x100, 0),
250 HDD_G_MODE_RATETAB(360, 0x200, 0),
251 HDD_G_MODE_RATETAB(480, 0x400, 0),
252 HDD_G_MODE_RATETAB(540, 0x800, 0),
253};
254
255static struct ieee80211_rate a_mode_rates[] =
256{
257 HDD_G_MODE_RATETAB(60, 0x10, 0),
258 HDD_G_MODE_RATETAB(90, 0x20, 0),
259 HDD_G_MODE_RATETAB(120, 0x40, 0),
260 HDD_G_MODE_RATETAB(180, 0x80, 0),
261 HDD_G_MODE_RATETAB(240, 0x100, 0),
262 HDD_G_MODE_RATETAB(360, 0x200, 0),
263 HDD_G_MODE_RATETAB(480, 0x400, 0),
264 HDD_G_MODE_RATETAB(540, 0x800, 0),
265};
266
267static struct ieee80211_supported_band wlan_hdd_band_2_4_GHZ =
268{
269 .channels = hdd_channels_2_4_GHZ,
270 .n_channels = ARRAY_SIZE(hdd_channels_2_4_GHZ),
271 .band = IEEE80211_BAND_2GHZ,
272 .bitrates = g_mode_rates,
273 .n_bitrates = g_mode_rates_size,
274 .ht_cap.ht_supported = 1,
275 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
276 | IEEE80211_HT_CAP_GRN_FLD
277 | IEEE80211_HT_CAP_DSSSCCK40
278 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
279 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
280 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
281 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
282 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
283 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
284};
285
Jeff Johnson295189b2012-06-20 16:38:30 -0700286static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_GHZ =
287{
288 .channels = hdd_social_channels_2_4_GHZ,
289 .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_GHZ),
290 .band = IEEE80211_BAND_2GHZ,
291 .bitrates = g_mode_rates,
292 .n_bitrates = g_mode_rates_size,
293 .ht_cap.ht_supported = 1,
294 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
295 | IEEE80211_HT_CAP_GRN_FLD
296 | IEEE80211_HT_CAP_DSSSCCK40
297 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
298 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
299 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
300 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
301 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
302 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
303};
Jeff Johnson295189b2012-06-20 16:38:30 -0700304
305static struct ieee80211_supported_band wlan_hdd_band_5_GHZ =
306{
307 .channels = hdd_channels_5_GHZ,
308 .n_channels = ARRAY_SIZE(hdd_channels_5_GHZ),
309 .band = IEEE80211_BAND_5GHZ,
310 .bitrates = a_mode_rates,
311 .n_bitrates = a_mode_rates_size,
312 .ht_cap.ht_supported = 1,
313 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
314 | IEEE80211_HT_CAP_GRN_FLD
315 | IEEE80211_HT_CAP_DSSSCCK40
316 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
317 | IEEE80211_HT_CAP_SGI_40
318 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
319 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
320 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
321 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
322 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
323 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
324};
325
326/* This structure contain information what kind of frame are expected in
327 TX/RX direction for each kind of interface */
328static const struct ieee80211_txrx_stypes
329wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
330 [NL80211_IFTYPE_STATION] = {
331 .tx = 0xffff,
332 .rx = BIT(SIR_MAC_MGMT_ACTION) |
333 BIT(SIR_MAC_MGMT_PROBE_REQ),
334 },
335 [NL80211_IFTYPE_AP] = {
336 .tx = 0xffff,
337 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
338 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
339 BIT(SIR_MAC_MGMT_PROBE_REQ) |
340 BIT(SIR_MAC_MGMT_DISASSOC) |
341 BIT(SIR_MAC_MGMT_AUTH) |
342 BIT(SIR_MAC_MGMT_DEAUTH) |
343 BIT(SIR_MAC_MGMT_ACTION),
344 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700345 [NL80211_IFTYPE_P2P_CLIENT] = {
346 .tx = 0xffff,
347 .rx = BIT(SIR_MAC_MGMT_ACTION) |
348 BIT(SIR_MAC_MGMT_PROBE_REQ),
349 },
350 [NL80211_IFTYPE_P2P_GO] = {
351 /* This is also same as for SoftAP */
352 .tx = 0xffff,
353 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
354 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
355 BIT(SIR_MAC_MGMT_PROBE_REQ) |
356 BIT(SIR_MAC_MGMT_DISASSOC) |
357 BIT(SIR_MAC_MGMT_AUTH) |
358 BIT(SIR_MAC_MGMT_DEAUTH) |
359 BIT(SIR_MAC_MGMT_ACTION),
360 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700361};
362
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800363#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800364static const struct ieee80211_iface_limit
365wlan_hdd_iface_limit[] = {
366 {
Sunil Ravia72c3992013-01-31 06:12:22 -0800367 /* max = 3 ; Our driver create two interfaces during driver init
368 * wlan0 and p2p0 interfaces. p2p0 is considered as station
369 * interface until a group is formed. In JB architecture, once the
370 * group is formed, interface type of p2p0 is changed to P2P GO or
371 * Client.
372 * When supplicant remove the group, it first issue a set interface
373 * cmd to change the mode back to Station. In JB this works fine as
374 * we advertize two station type interface during driver init.
375 * Some vendors create separate interface for P2P GO/Client,
376 * after group formation(Third one). But while group remove
377 * supplicant first tries to change the mode(3rd interface) to STATION
378 * But as we advertized only two sta type interfaces nl80211 was
379 * returning error for the third one which was leading to failure in
380 * delete interface. Ideally while removing the group, supplicant
381 * should not try to change the 3rd interface mode to Station type.
382 * Till we get a fix in wpa_supplicant, we advertize max STA
383 * interface type to 3
384 */
385 .max = 3,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800386 .types = BIT(NL80211_IFTYPE_STATION),
387 },
388 {
389 .max = 1,
390 .types = BIT(NL80211_IFTYPE_AP),
391 },
392 {
393 .max = 1,
394 .types = BIT(NL80211_IFTYPE_P2P_GO) |
395 BIT(NL80211_IFTYPE_P2P_CLIENT),
396 },
397};
398
399/* By default, only single channel concurrency is allowed */
400static struct ieee80211_iface_combination
401wlan_hdd_iface_combination = {
402 .limits = wlan_hdd_iface_limit,
403 .num_different_channels = 1,
Sunil Ravia72c3992013-01-31 06:12:22 -0800404 /*
405 * max = WLAN_MAX_INTERFACES ; JellyBean architecture creates wlan0
406 * and p2p0 interfaces during driver init
407 * Some vendors create separate interface for P2P operations.
408 * wlan0: STA interface
409 * p2p0: P2P Device interface, action frames goes
410 * through this interface.
411 * p2p-xx: P2P interface, After GO negotiation this interface is
412 * created for p2p operations(GO/CLIENT interface).
413 */
414 .max_interfaces = WLAN_MAX_INTERFACES,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800415 .n_limits = ARRAY_SIZE(wlan_hdd_iface_limit),
416 .beacon_int_infra_match = false,
417};
418#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800419
Jeff Johnson295189b2012-06-20 16:38:30 -0700420static struct cfg80211_ops wlan_hdd_cfg80211_ops;
421
422/* Data rate 100KBPS based on IE Index */
423struct index_data_rate_type
424{
425 v_U8_t beacon_rate_index;
426 v_U16_t supported_rate[4];
427};
428
429/* 11B, 11G Rate table include Basic rate and Extended rate
430 The IDX field is the rate index
431 The HI field is the rate when RSSI is strong or being ignored
432 (in this case we report actual rate)
433 The MID field is the rate when RSSI is moderate
434 (in this case we cap 11b rates at 5.5 and 11g rates at 24)
435 The LO field is the rate when RSSI is low
436 (in this case we don't report rates, actual current rate used)
437 */
438static const struct
439{
440 v_U8_t beacon_rate_index;
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700441 v_U16_t supported_rate[4];
Jeff Johnson295189b2012-06-20 16:38:30 -0700442} supported_data_rate[] =
443{
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700444/* IDX HI HM LM LO (RSSI-based index */
445 {2, { 10, 10, 10, 0}},
446 {4, { 20, 20, 10, 0}},
447 {11, { 55, 20, 10, 0}},
448 {12, { 60, 55, 20, 0}},
449 {18, { 90, 55, 20, 0}},
450 {22, {110, 55, 20, 0}},
451 {24, {120, 90, 60, 0}},
452 {36, {180, 120, 60, 0}},
453 {44, {220, 180, 60, 0}},
454 {48, {240, 180, 90, 0}},
455 {66, {330, 180, 90, 0}},
456 {72, {360, 240, 90, 0}},
457 {96, {480, 240, 120, 0}},
458 {108, {540, 240, 120, 0}}
Jeff Johnson295189b2012-06-20 16:38:30 -0700459};
460
461/* MCS Based rate table */
462static struct index_data_rate_type supported_mcs_rate[] =
463{
464/* MCS L20 L40 S20 S40 */
465 {0, {65, 135, 72, 150}},
466 {1, {130, 270, 144, 300}},
467 {2, {195, 405, 217, 450}},
468 {3, {260, 540, 289, 600}},
469 {4, {390, 810, 433, 900}},
470 {5, {520, 1080, 578, 1200}},
471 {6, {585, 1215, 650, 1350}},
472 {7, {650, 1350, 722, 1500}}
473};
474
Leo Chang6f8870f2013-03-26 18:11:36 -0700475#ifdef WLAN_FEATURE_11AC
476
477#define DATA_RATE_11AC_MCS_MASK 0x0F
478
479struct index_vht_data_rate_type
480{
481 v_U8_t beacon_rate_index;
482 v_U16_t supported_rate[2];
483};
484
485typedef enum
486{
487 DATA_RATE_11AC_MAX_MCS_7,
488 DATA_RATE_11AC_MAX_MCS_8,
489 DATA_RATE_11AC_MAX_MCS_9,
490 DATA_RATE_11AC_MAX_MCS_NA
491} eDataRate11ACMaxMcs;
492
493/* MCS Based VHT rate table */
494static struct index_vht_data_rate_type supported_vht_mcs_rate[] =
495{
496/* MCS L80 S80 */
497 {0, {293, 325}},
498 {1, {585, 650}},
499 {2, {878, 975}},
500 {3, {1170, 1300}},
501 {4, {1755, 1950}},
502 {5, {2340, 2600}},
503 {6, {2633, 2925}},
504 {7, {2925, 3250}},
505 {8, {3510, 3900}},
506 {9, {3900, 4333}}
507};
508#endif /* WLAN_FEATURE_11AC */
509
Jeff Johnson295189b2012-06-20 16:38:30 -0700510extern struct net_device_ops net_ops_struct;
511
512/*
513 * FUNCTION: wlan_hdd_cfg80211_init
514 * This function is called by hdd_wlan_startup()
515 * during initialization.
516 * This function is used to initialize and register wiphy structure.
517 */
518struct wiphy *wlan_hdd_cfg80211_init(int priv_size)
519{
520 struct wiphy *wiphy;
521 ENTER();
522
523 /*
524 * Create wiphy device
525 */
526 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
527
528 if (!wiphy)
529 {
530 /* Print error and jump into err label and free the memory */
531 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__);
532 return NULL;
533 }
534
535 return wiphy;
536}
537
538/*
539 * FUNCTION: wlan_hdd_cfg80211_update_band
540 * This function is called from the supplicant through a
541 * private ioctl to change the band value
542 */
543int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
544{
Jeff Johnsone7245742012-09-05 17:12:55 -0700545 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700546 switch(eBand)
547 {
548 case eCSR_BAND_24:
549 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
550 wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
551 break;
552 case eCSR_BAND_5G:
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700553 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700554 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
555 break;
556 case eCSR_BAND_ALL:
557 default:
558 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
559 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
560 }
561 return 0;
562}
563/*
564 * FUNCTION: wlan_hdd_cfg80211_init
565 * This function is called by hdd_wlan_startup()
566 * during initialization.
567 * This function is used to initialize and register wiphy structure.
568 */
569int wlan_hdd_cfg80211_register(struct device *dev,
570 struct wiphy *wiphy,
571 hdd_config_t *pCfg
572 )
573{
Jeff Johnsone7245742012-09-05 17:12:55 -0700574 ENTER();
575
Jeff Johnson295189b2012-06-20 16:38:30 -0700576 /* Now bind the underlying wlan device with wiphy */
577 set_wiphy_dev(wiphy, dev);
578
579 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
580
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700581 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700582
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700583#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700584 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
585 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
586 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
Jeff Johnsone7245742012-09-05 17:12:55 -0700587 | WIPHY_FLAG_OFFCHAN_TX;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700588#endif
Srinivas Girigowda640728a2013-03-28 12:21:54 -0700589#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
590 if (pCfg->isFastTransitionEnabled
James Zmuda77fb5ae2013-01-29 08:00:17 -0800591#ifdef FEATURE_WLAN_LFR
Srinivas Girigowda640728a2013-03-28 12:21:54 -0700592 || pCfg->isFastRoamIniFeatureEnabled
593#endif
594#ifdef FEATURE_WLAN_CCX
595 || pCfg->isCcxIniFeatureEnabled
596#endif
597 )
598 {
599 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
600 }
James Zmuda77fb5ae2013-01-29 08:00:17 -0800601#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800602#ifdef FEATURE_WLAN_TDLS
603 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
604 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
605#endif
606
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700607 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
608 driver can still register regulatory callback and
609 it will get CRDA setting in wiphy->band[], but
610 driver need to determine what to do with both
611 regulatory settings */
612 wiphy->reg_notifier = wlan_hdd_crda_reg_notifier;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700613
Jeff Johnson295189b2012-06-20 16:38:30 -0700614 wiphy->max_scan_ssids = MAX_SCAN_SSID;
615
616 wiphy->max_scan_ie_len = 200 ; //TODO: define a macro
617
618 /* Supports STATION & AD-HOC modes right now */
619 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
620 | BIT(NL80211_IFTYPE_ADHOC)
Jeff Johnson295189b2012-06-20 16:38:30 -0700621 | BIT(NL80211_IFTYPE_P2P_CLIENT)
622 | BIT(NL80211_IFTYPE_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -0700623 | BIT(NL80211_IFTYPE_AP);
624
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800625#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800626 if( pCfg->enableMCC )
627 {
628 /* Currently, supports up to two channels */
629 wlan_hdd_iface_combination.num_different_channels = 2;
630
631 if( !pCfg->allowMCCGODiffBI )
632 wlan_hdd_iface_combination.beacon_int_infra_match = true;
633
634 }
635 wiphy->iface_combinations = &wlan_hdd_iface_combination;
636 wiphy->n_iface_combinations = 1;
637#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800638
Jeff Johnson295189b2012-06-20 16:38:30 -0700639 /* Before registering we need to update the ht capabilitied based
640 * on ini values*/
641 if( !pCfg->ShortGI20MhzEnable )
642 {
643 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
644 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
645 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
646 }
647
648 if( !pCfg->ShortGI40MhzEnable )
649 {
650 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
651 }
652
653 if( !pCfg->nChannelBondingMode5GHz )
654 {
655 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
656 }
657
658 /*Initialize band capability*/
659 switch(pCfg->nBandCapability)
660 {
661 case eCSR_BAND_24:
662 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
663 break;
664 case eCSR_BAND_5G:
Jeff Johnson295189b2012-06-20 16:38:30 -0700665 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700666 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
667 break;
668 case eCSR_BAND_ALL:
669 default:
670 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
671 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
672 }
673 /*Initialise the supported cipher suite details*/
674 wiphy->cipher_suites = hdd_cipher_suites;
675 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
676
677 /*signal strength in mBm (100*dBm) */
678 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
679
680#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -0700681 wiphy->max_remain_on_channel_duration = 1000;
682#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700683
684 /* Register our wiphy dev with cfg80211 */
685 if (0 > wiphy_register(wiphy))
686 {
687 /* print eror */
688 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
689 return -EIO;
690 }
691
692 EXIT();
693 return 0;
694}
695
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700696/* In this function we will try to get default country code from crda.
697 If the gCrdaDefaultCountryCode is configured in ini file,
698 we will try to call user space crda to get the regulatory settings for
699 that country. We will timeout if we can't get it from crda.
700 It's called by hdd_wlan_startup() after wlan_hdd_cfg80211_register.
701*/
702int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg)
703{
704 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
705 if (memcmp(pCfg->crdaDefaultCountryCode,
706 CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) != 0)
707 {
708 init_completion(&pHddCtx->driver_crda_req);
709 regulatory_hint(wiphy, pCfg->crdaDefaultCountryCode);
710 wait_for_completion_interruptible_timeout(&pHddCtx->driver_crda_req,
711 CRDA_WAIT_TIME);
Yunsen Wange3ba1fb2013-04-05 15:04:43 -0700712 /* if the country is not found from current regulatory.bin,
713 fall back to world domain */
714 if (is_crda_regulatory_entry_valid() == VOS_FALSE)
715 crda_regulatory_entry_default(pCfg->crdaDefaultCountryCode, NUM_REG_DOMAINS-1);
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700716 }
717 return 0;
718}
719
Jeff Johnson295189b2012-06-20 16:38:30 -0700720/* In this function we will do all post VOS start initialization.
721 In this function we will register for all frame in which supplicant
722 is interested.
723*/
724void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
725{
Jeff Johnson295189b2012-06-20 16:38:30 -0700726 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
727 /* Register for all P2P action, public action etc frames */
728 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
729
Jeff Johnsone7245742012-09-05 17:12:55 -0700730 ENTER();
731
Jeff Johnson295189b2012-06-20 16:38:30 -0700732 /* Right now we are registering these frame when driver is getting
733 initialized. Once we will move to 2.6.37 kernel, in which we have
734 frame register ops, we will move this code as a part of that */
735 /* GAS Initial Request */
736 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
737 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
738
739 /* GAS Initial Response */
740 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
741 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
742
743 /* GAS Comeback Request */
744 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
745 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
746
747 /* GAS Comeback Response */
748 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
749 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
750
751 /* P2P Public Action */
752 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
753 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
754 P2P_PUBLIC_ACTION_FRAME_SIZE );
755
756 /* P2P Action */
757 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
758 (v_U8_t*)P2P_ACTION_FRAME,
759 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -0700760
761#ifdef WLAN_FEATURE_11W
762 /* SA Query Response Action Frame */
763 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
764 (v_U8_t*)SA_QUERY_FRAME_RSP,
765 SA_QUERY_FRAME_RSP_SIZE );
766#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -0700767}
768
769void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
770{
Jeff Johnson295189b2012-06-20 16:38:30 -0700771 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
772 /* Register for all P2P action, public action etc frames */
773 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
774
Jeff Johnsone7245742012-09-05 17:12:55 -0700775 ENTER();
776
Jeff Johnson295189b2012-06-20 16:38:30 -0700777 /* Right now we are registering these frame when driver is getting
778 initialized. Once we will move to 2.6.37 kernel, in which we have
779 frame register ops, we will move this code as a part of that */
780 /* GAS Initial Request */
781
782 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
783 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
784
785 /* GAS Initial Response */
786 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
787 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
788
789 /* GAS Comeback Request */
790 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
791 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
792
793 /* GAS Comeback Response */
794 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
795 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
796
797 /* P2P Public Action */
798 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
799 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
800 P2P_PUBLIC_ACTION_FRAME_SIZE );
801
802 /* P2P Action */
803 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
804 (v_U8_t*)P2P_ACTION_FRAME,
805 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -0700806
807#ifdef WLAN_FEATURE_11W
808 /* SA Query Response Action Frame */
809 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
810 (v_U8_t*)SA_QUERY_FRAME_RSP,
811 SA_QUERY_FRAME_RSP_SIZE );
812#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -0700813}
814
815#ifdef FEATURE_WLAN_WAPI
816void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
817 const u8 *mac_addr, u8 *key , int key_Len)
818{
819 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
820 tCsrRoamSetKey setKey;
821 v_BOOL_t isConnected = TRUE;
822 int status = 0;
823 v_U32_t roamId= 0xFF;
824 tANI_U8 *pKeyPtr = NULL;
825 int n = 0;
826
827 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
828 __func__,pAdapter->device_mode);
829
Gopichand Nakkalae7480202013-02-11 15:24:22 +0530830 vos_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Jeff Johnson295189b2012-06-20 16:38:30 -0700831 setKey.keyId = key_index; // Store Key ID
832 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
833 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
834 setKey.paeRole = 0 ; // the PAE role
835 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
836 {
837 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
838 }
839 else
840 {
841 isConnected = hdd_connIsConnected(pHddStaCtx);
842 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
843 }
844 setKey.keyLength = key_Len;
845 pKeyPtr = setKey.Key;
846 memcpy( pKeyPtr, key, key_Len);
847
848 hddLog(VOS_TRACE_LEVEL_INFO,"\n%s: WAPI KEY LENGTH:0x%04x",
849 __func__, key_Len);
850 for (n = 0 ; n < key_Len; n++)
851 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
852 __func__,n,setKey.Key[n]);
853
854 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
855 if ( isConnected )
856 {
857 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
858 pAdapter->sessionId, &setKey, &roamId );
859 }
860 if ( status != 0 )
861 {
862 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
863 "[%4d] sme_RoamSetKey returned ERROR status= %d",
864 __LINE__, status );
865 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
866 }
867}
868#endif /* FEATURE_WLAN_WAPI*/
869
870#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
871int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
872 beacon_data_t **ppBeacon,
873 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700874#else
875int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
876 beacon_data_t **ppBeacon,
877 struct cfg80211_beacon_data *params,
878 int dtim_period)
879#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700880{
881 int size;
882 beacon_data_t *beacon = NULL;
883 beacon_data_t *old = NULL;
884 int head_len,tail_len;
885
Jeff Johnsone7245742012-09-05 17:12:55 -0700886 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700887 if (params->head && !params->head_len)
888 return -EINVAL;
889
890 old = pAdapter->sessionCtx.ap.beacon;
891
892 if (!params->head && !old)
893 return -EINVAL;
894
895 if (params->tail && !params->tail_len)
896 return -EINVAL;
897
898#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
899 /* Kernel 3.0 is not updating dtim_period for set beacon */
900 if (!params->dtim_period)
901 return -EINVAL;
902#endif
903
904 if(params->head)
905 head_len = params->head_len;
906 else
907 head_len = old->head_len;
908
909 if(params->tail || !old)
910 tail_len = params->tail_len;
911 else
912 tail_len = old->tail_len;
913
914 size = sizeof(beacon_data_t) + head_len + tail_len;
915
916 beacon = kzalloc(size, GFP_KERNEL);
917
918 if( beacon == NULL )
919 return -ENOMEM;
920
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700921#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700922 if(params->dtim_period || !old )
923 beacon->dtim_period = params->dtim_period;
924 else
925 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700926#else
927 if(dtim_period || !old )
928 beacon->dtim_period = dtim_period;
929 else
930 beacon->dtim_period = old->dtim_period;
931#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700932
933 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
934 beacon->tail = beacon->head + head_len;
935 beacon->head_len = head_len;
936 beacon->tail_len = tail_len;
937
938 if(params->head) {
939 memcpy (beacon->head,params->head,beacon->head_len);
940 }
941 else {
942 if(old)
943 memcpy (beacon->head,old->head,beacon->head_len);
944 }
945
946 if(params->tail) {
947 memcpy (beacon->tail,params->tail,beacon->tail_len);
948 }
949 else {
950 if(old)
951 memcpy (beacon->tail,old->tail,beacon->tail_len);
952 }
953
954 *ppBeacon = beacon;
955
956 kfree(old);
957
958 return 0;
959
960}
Jeff Johnson295189b2012-06-20 16:38:30 -0700961
962v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
963{
964 int left = length;
965 v_U8_t *ptr = pIes;
966 v_U8_t elem_id,elem_len;
967
968 while(left >= 2)
969 {
970 elem_id = ptr[0];
971 elem_len = ptr[1];
972 left -= 2;
973 if(elem_len > left)
974 {
975 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700976 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -0700977 eid,elem_len,left);
978 return NULL;
979 }
980 if (elem_id == eid)
981 {
982 return ptr;
983 }
984
985 left -= elem_len;
986 ptr += (elem_len + 2);
987 }
988 return NULL;
989}
990
Jeff Johnson295189b2012-06-20 16:38:30 -0700991/* Check if rate is 11g rate or not */
992static int wlan_hdd_rate_is_11g(u8 rate)
993{
994 u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 104}; /* actual rate * 2 */
995 u8 i;
996 for (i = 0; i < 8; i++)
997 {
998 if(rate == gRateArray[i])
999 return TRUE;
1000 }
1001 return FALSE;
1002}
1003
1004/* Check for 11g rate and set proper 11g only mode */
1005static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
1006 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
1007{
1008 u8 i, num_rates = pIe[0];
1009
1010 pIe += 1;
1011 for ( i = 0; i < num_rates; i++)
1012 {
1013 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
1014 {
1015 /* If rate set have 11g rate than change the mode to 11G */
1016 *pSapHw_mode = eSAP_DOT11_MODE_11g;
1017 if (pIe[i] & BASIC_RATE_MASK)
1018 {
1019 /* If we have 11g rate as basic rate, it means mode
1020 is 11g only mode.
1021 */
1022 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
1023 *pCheckRatesfor11g = FALSE;
1024 }
1025 }
1026 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
1027 {
1028 *require_ht = TRUE;
1029 }
1030 }
1031 return;
1032}
1033
1034static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
1035{
1036 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1037 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1038 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1039 u8 checkRatesfor11g = TRUE;
1040 u8 require_ht = FALSE;
1041 u8 *pIe=NULL;
1042
1043 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
1044
1045 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
1046 pBeacon->head_len, WLAN_EID_SUPP_RATES);
1047 if (pIe != NULL)
1048 {
1049 pIe += 1;
1050 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1051 &pConfig->SapHw_mode);
1052 }
1053
1054 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1055 WLAN_EID_EXT_SUPP_RATES);
1056 if (pIe != NULL)
1057 {
1058
1059 pIe += 1;
1060 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1061 &pConfig->SapHw_mode);
1062 }
1063
1064 if( pConfig->channel > 14 )
1065 {
1066 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
1067 }
1068
1069 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1070 WLAN_EID_HT_CAPABILITY);
1071
1072 if(pIe)
1073 {
1074 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
1075 if(require_ht)
1076 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
1077 }
1078}
1079
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301080static int wlan_hdd_add_ie(hdd_adapter_t* pHostapdAdapter, v_U8_t *genie,
1081 v_U8_t *total_ielen, v_U8_t *oui, v_U8_t oui_size)
1082{
1083 v_U8_t ielen = 0;
1084 v_U8_t *pIe = NULL;
1085 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1086
1087 pIe = wlan_hdd_get_vendor_oui_ie_ptr(oui, oui_size,
1088 pBeacon->tail, pBeacon->tail_len);
1089
1090 if (pIe)
1091 {
1092 ielen = pIe[1] + 2;
1093 if ((*total_ielen + ielen) <= MAX_GENIE_LEN)
1094 {
1095 vos_mem_copy(&genie[*total_ielen], pIe, ielen);
1096 }
1097 else
1098 {
1099 hddLog( VOS_TRACE_LEVEL_ERROR, "**Ie Length is too big***");
1100 return -EINVAL;
1101 }
1102 *total_ielen += ielen;
1103 }
1104 return 0;
1105}
1106
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001107#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001108static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1109 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001110#else
1111static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1112 struct cfg80211_beacon_data *params)
1113#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001114{
1115 v_U8_t *genie;
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301116 v_U8_t total_ielen = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001117 v_U8_t addIE[1] = {0};
Jeff Johnsone7245742012-09-05 17:12:55 -07001118 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001119
1120 genie = vos_mem_malloc(MAX_GENIE_LEN);
1121
1122 if(genie == NULL) {
1123
1124 return -ENOMEM;
1125 }
1126
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301127 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1128 &total_ielen, WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001129 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301130 ret = -EINVAL;
1131 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001132 }
1133
1134#ifdef WLAN_FEATURE_WFD
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301135 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1136 &total_ielen, WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE))
1137 {
1138 ret = -EINVAL;
1139 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001140 }
1141#endif
1142
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301143 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1144 &total_ielen, P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001145 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301146 ret = -EINVAL;
1147 goto done;
1148 }
1149
1150 if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode)
1151 {
1152 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1153 &total_ielen, SS_OUI_TYPE, SS_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001154 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301155 ret = -EINVAL;
1156 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001157 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001158 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001159
1160 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1161 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1162 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1163 {
1164 hddLog(LOGE,
1165 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001166 ret = -EINVAL;
1167 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001168 }
1169
1170 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1171 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1172 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1173 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1174 ==eHAL_STATUS_FAILURE)
1175 {
1176 hddLog(LOGE,
1177 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001178 ret = -EINVAL;
1179 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001180 }
1181
1182 // Added for ProResp IE
1183 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1184 {
1185 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1186 u8 probe_rsp_ie_len[3] = {0};
1187 u8 counter = 0;
1188 /* Check Probe Resp Length if it is greater then 255 then Store
1189 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1190 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1191 Store More then 255 bytes into One Variable.
1192 */
1193 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1194 {
1195 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1196 {
1197 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1198 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1199 }
1200 else
1201 {
1202 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1203 rem_probe_resp_ie_len = 0;
1204 }
1205 }
1206
1207 rem_probe_resp_ie_len = 0;
1208
1209 if (probe_rsp_ie_len[0] > 0)
1210 {
1211 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1212 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1213 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1214 probe_rsp_ie_len[0], NULL,
1215 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1216 {
1217 hddLog(LOGE,
1218 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001219 ret = -EINVAL;
1220 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001221 }
1222 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1223 }
1224
1225 if (probe_rsp_ie_len[1] > 0)
1226 {
1227 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1228 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1229 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1230 probe_rsp_ie_len[1], NULL,
1231 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1232 {
1233 hddLog(LOGE,
1234 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001235 ret = -EINVAL;
1236 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001237 }
1238 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1239 }
1240
1241 if (probe_rsp_ie_len[2] > 0)
1242 {
1243 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1244 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1245 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1246 probe_rsp_ie_len[2], NULL,
1247 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1248 {
1249 hddLog(LOGE,
1250 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001251 ret = -EINVAL;
1252 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001253 }
1254 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1255 }
1256
1257 if (probe_rsp_ie_len[1] == 0 )
1258 {
1259 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1260 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1261 eANI_BOOLEAN_FALSE) )
1262 {
1263 hddLog(LOGE,
1264 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1265 }
1266 }
1267
1268 if (probe_rsp_ie_len[2] == 0 )
1269 {
1270 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1271 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1272 eANI_BOOLEAN_FALSE) )
1273 {
1274 hddLog(LOGE,
1275 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1276 }
1277 }
1278
1279 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1280 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1281 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1282 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1283 == eHAL_STATUS_FAILURE)
1284 {
1285 hddLog(LOGE,
1286 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001287 ret = -EINVAL;
1288 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001289 }
1290 }
1291 else
1292 {
1293 // Reset WNI_CFG_PROBE_RSP Flags
1294 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1295
1296 hddLog(VOS_TRACE_LEVEL_INFO,
1297 "%s: No Probe Response IE received in set beacon",
1298 __func__);
1299 }
1300
1301 // Added for AssocResp IE
1302 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1303 {
1304 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1305 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1306 params->assocresp_ies_len, NULL,
1307 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1308 {
1309 hddLog(LOGE,
1310 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001311 ret = -EINVAL;
1312 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001313 }
1314
1315 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1316 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1317 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1318 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1319 == eHAL_STATUS_FAILURE)
1320 {
1321 hddLog(LOGE,
1322 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001323 ret = -EINVAL;
1324 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001325 }
1326 }
1327 else
1328 {
1329 hddLog(VOS_TRACE_LEVEL_INFO,
1330 "%s: No Assoc Response IE received in set beacon",
1331 __func__);
1332
1333 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1334 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1335 eANI_BOOLEAN_FALSE) )
1336 {
1337 hddLog(LOGE,
1338 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1339 }
1340 }
1341
Jeff Johnsone7245742012-09-05 17:12:55 -07001342done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001343 vos_mem_free(genie);
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301344 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07001345}
Jeff Johnson295189b2012-06-20 16:38:30 -07001346
1347/*
1348 * FUNCTION: wlan_hdd_validate_operation_channel
1349 * called by wlan_hdd_cfg80211_start_bss() and
1350 * wlan_hdd_cfg80211_set_channel()
1351 * This function validates whether given channel is part of valid
1352 * channel list.
1353 */
1354static VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
1355{
1356
1357 v_U32_t num_ch = 0;
1358 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1359 u32 indx = 0;
1360 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301361 v_U8_t fValidChannel = FALSE, count = 0;
1362 hdd_config_t *hdd_pConfig_ini= (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07001363
1364 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1365
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301366 if ( hdd_pConfig_ini->sapAllowAllChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001367 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301368 /* Validate the channel */
1369 for (count = RF_CHAN_1 ; count <= RF_CHAN_165 ; count++)
Jeff Johnson295189b2012-06-20 16:38:30 -07001370 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301371 if ( channel == rfChannels[count].channelNum )
1372 {
1373 fValidChannel = TRUE;
1374 break;
1375 }
1376 }
1377 if (fValidChannel != TRUE)
1378 {
1379 hddLog(VOS_TRACE_LEVEL_ERROR,
1380 "%s: Invalid Channel [%d]", __func__, channel);
1381 return VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001382 }
1383 }
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301384 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001385 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301386 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1387 valid_ch, &num_ch))
1388 {
1389 hddLog(VOS_TRACE_LEVEL_ERROR,
1390 "%s: failed to get valid channel list", __func__);
1391 return VOS_STATUS_E_FAILURE;
1392 }
1393 for (indx = 0; indx < num_ch; indx++)
1394 {
1395 if (channel == valid_ch[indx])
1396 {
1397 break;
1398 }
1399 }
1400
1401 if (indx >= num_ch)
1402 {
1403 hddLog(VOS_TRACE_LEVEL_ERROR,
1404 "%s: Invalid Channel [%d]", __func__, channel);
1405 return VOS_STATUS_E_FAILURE;
1406 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001407 }
1408 return VOS_STATUS_SUCCESS;
1409
1410}
1411
Viral Modi3a32cc52013-02-08 11:14:52 -08001412/**
1413 * FUNCTION: wlan_hdd_cfg80211_set_channel
1414 * This function is used to set the channel number
1415 */
1416static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
1417 struct ieee80211_channel *chan,
1418 enum nl80211_channel_type channel_type
1419 )
1420{
1421 v_U32_t num_ch = 0;
Jeff Johnson4416a782013-03-25 14:17:50 -07001422 int channel = 0;
Viral Modi3a32cc52013-02-08 11:14:52 -08001423 hdd_adapter_t *pAdapter = NULL;
1424 int freq = chan->center_freq; /* freq is in MHZ */
1425
1426 ENTER();
1427
1428 if( NULL == dev )
1429 {
1430 hddLog(VOS_TRACE_LEVEL_ERROR,
1431 "%s: Called with dev = NULL.\n", __func__);
1432 return -ENODEV;
1433 }
1434 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1435
1436 hddLog(VOS_TRACE_LEVEL_INFO,
1437 "%s: device_mode = %d freq = %d \n",__func__,
1438 pAdapter->device_mode, chan->center_freq);
1439 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1440 {
1441 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1442 return -EAGAIN;
1443 }
1444
1445 /*
1446 * Do freq to chan conversion
1447 * TODO: for 11a
1448 */
1449
1450 channel = ieee80211_frequency_to_channel(freq);
1451
1452 /* Check freq range */
1453 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
1454 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
1455 {
1456 hddLog(VOS_TRACE_LEVEL_ERROR,
1457 "%s: Channel [%d] is outside valid range from %d to %d\n",
1458 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
1459 WNI_CFG_CURRENT_CHANNEL_STAMAX);
1460 return -EINVAL;
1461 }
1462
1463 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1464
Gopichand Nakkala6ab19562013-03-07 13:59:42 +05301465 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode) &&
1466 (WLAN_HDD_P2P_GO != pAdapter->device_mode))
Viral Modi3a32cc52013-02-08 11:14:52 -08001467 {
1468 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
1469 {
1470 hddLog(VOS_TRACE_LEVEL_ERROR,
1471 "%s: Invalid Channel [%d] \n", __func__, channel);
1472 return -EINVAL;
1473 }
1474 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1475 "%s: set channel to [%d] for device mode =%d",
1476 __func__, channel,pAdapter->device_mode);
1477 }
1478 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Viral Modi3a32cc52013-02-08 11:14:52 -08001479 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Viral Modi3a32cc52013-02-08 11:14:52 -08001480 )
1481 {
1482 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
1483 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
1484 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1485
1486 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
1487 {
1488 /* Link is up then return cant set channel*/
1489 hddLog( VOS_TRACE_LEVEL_ERROR,
1490 "%s: IBSS Associated, can't set the channel\n", __func__);
1491 return -EINVAL;
1492 }
1493
1494 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
1495 pHddStaCtx->conn_info.operationChannel = channel;
1496 pRoamProfile->ChannelInfo.ChannelList =
1497 &pHddStaCtx->conn_info.operationChannel;
1498 }
1499 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Viral Modi3a32cc52013-02-08 11:14:52 -08001500 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Viral Modi3a32cc52013-02-08 11:14:52 -08001501 )
1502 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301503 if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
1504 {
1505 if(VOS_STATUS_SUCCESS !=
1506 wlan_hdd_validate_operation_channel(pAdapter,channel))
1507 {
1508 hddLog(VOS_TRACE_LEVEL_ERROR,
1509 "%s: Invalid Channel [%d] \n", __func__, channel);
1510 return -EINVAL;
1511 }
1512 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1513 }
1514 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
Viral Modi3a32cc52013-02-08 11:14:52 -08001515 {
1516 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
1517
1518 /* If auto channel selection is configured as enable/ 1 then ignore
1519 channel set by supplicant
1520 */
1521 if ( cfg_param->apAutoChannelSelection )
1522 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301523 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel =
1524 AUTO_CHANNEL_SELECT;
Viral Modi3a32cc52013-02-08 11:14:52 -08001525 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1526 "%s: set channel to auto channel (0) for device mode =%d",
1527 __func__, pAdapter->device_mode);
1528 }
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301529 else
1530 {
1531 if(VOS_STATUS_SUCCESS !=
1532 wlan_hdd_validate_operation_channel(pAdapter,channel))
1533 {
1534 hddLog(VOS_TRACE_LEVEL_ERROR,
1535 "%s: Invalid Channel [%d] \n", __func__, channel);
1536 return -EINVAL;
1537 }
1538 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1539 }
Viral Modi3a32cc52013-02-08 11:14:52 -08001540 }
1541 }
1542 else
1543 {
1544 hddLog(VOS_TRACE_LEVEL_FATAL,
1545 "%s: Invalid device mode failed to set valid channel", __func__);
1546 return -EINVAL;
1547 }
1548 EXIT();
1549 return 0;
1550}
1551
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301552/*
1553 * FUNCTION: wlan_hdd_select_cbmode
1554 * called by wlan_hdd_cfg80211_start_bss() and
1555 * This function selects the cbmode based on primary channel
1556 */
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001557VOS_STATUS wlan_sap_select_cbmode(void *pAdapter,eSapPhyMode SapHw_mode, v_U8_t channel)
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301558{
1559 tSmeConfigParams smeConfig;
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001560 hdd_context_t *pHddCtx = ( hdd_context_t *) pAdapter;
1561 hdd_config_t *pConfigIni = ((hdd_context_t *)(pAdapter))->cfg_ini;
1562
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301563 if(
1564#ifdef WLAN_FEATURE_11AC
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001565 SapHw_mode != eSAP_DOT11_MODE_11ac &&
1566 SapHw_mode != eSAP_DOT11_MODE_11ac_ONLY &&
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301567#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001568 SapHw_mode != eSAP_DOT11_MODE_11n &&
1569 SapHw_mode != eSAP_DOT11_MODE_11n_ONLY
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301570 )
1571 {
1572 return VOS_STATUS_SUCCESS;
1573 }
1574
1575 if (!pConfigIni->nChannelBondingMode5GHz) {
1576 return VOS_STATUS_SUCCESS;
1577 }
1578
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001579 //channel = pSapConfig->channel;
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301580 vos_mem_zero(&smeConfig, sizeof (tSmeConfigParams));
1581
1582 sme_GetConfigParam(pHddCtx->hHal, &smeConfig);
1583
1584#ifdef WLAN_FEATURE_11AC
1585
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001586 if ( SapHw_mode == eSAP_DOT11_MODE_11ac ||
1587 SapHw_mode == eSAP_DOT11_MODE_11ac_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301588 {
1589 if ( channel== 36 || channel == 52 || channel == 100 ||
1590 channel == 116 || channel == 149 )
1591 {
1592 smeConfig.csrConfig.channelBondingMode5GHz =
1593 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW - 1;
1594 }
1595 else if ( channel == 40 || channel == 56 || channel == 104 ||
1596 channel == 120 || channel == 153 )
1597 {
1598 smeConfig.csrConfig.channelBondingMode5GHz =
1599 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW - 1;
1600 }
1601 else if ( channel == 44 || channel == 60 || channel == 108 ||
1602 channel == 124 || channel == 157 )
1603 {
1604 smeConfig.csrConfig.channelBondingMode5GHz =
1605 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH -1;
1606 }
1607 else if ( channel == 48 || channel == 64 || channel == 112 ||
1608 channel == 128 || channel == 161 )
1609 {
1610 smeConfig.csrConfig.channelBondingMode5GHz =
1611 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH - 1;
1612 }
Shailender Karmuchi84f11f02013-02-12 17:11:45 -08001613 else if ( channel == 165 )
1614 {
1615 smeConfig.csrConfig.channelBondingMode5GHz = 0;
1616 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301617 }
1618#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001619 if ( SapHw_mode == eSAP_DOT11_MODE_11n ||
1620 SapHw_mode == eSAP_DOT11_MODE_11n_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301621 {
1622 if ( channel== 40 || channel == 48 || channel == 56 ||
1623 channel == 64 || channel == 104 || channel == 112 ||
1624 channel == 120 || channel == 128 || channel == 136 ||
1625 channel == 144 || channel == 153 || channel == 161 )
1626 {
1627 smeConfig.csrConfig.channelBondingMode5GHz = 1;
1628 }
1629 else if ( channel== 36 || channel == 44 || channel == 52 ||
1630 channel == 60 || channel == 100 || channel == 108 ||
1631 channel == 116 || channel == 124 || channel == 132 ||
1632 channel == 140 || channel == 149 || channel == 157 )
1633 {
1634 smeConfig.csrConfig.channelBondingMode5GHz = 2;
1635 }
Shailender Karmuchi84f11f02013-02-12 17:11:45 -08001636 else if ( channel == 165 )
1637 {
1638 smeConfig.csrConfig.channelBondingMode5GHz = 0;
1639 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301640 }
1641 pr_info ("cbmode selected=%ld\n",smeConfig.csrConfig.channelBondingMode5GHz);
1642
1643 sme_UpdateConfig (pHddCtx->hHal,&smeConfig);
1644 return VOS_STATUS_SUCCESS;
1645}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001646
Jeff Johnson295189b2012-06-20 16:38:30 -07001647#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1648static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1649 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001650#else
1651static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1652 struct cfg80211_beacon_data *params,
1653 const u8 *ssid, size_t ssid_len,
1654 enum nl80211_hidden_ssid hidden_ssid)
1655#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001656{
1657 tsap_Config_t *pConfig;
1658 beacon_data_t *pBeacon = NULL;
1659 struct ieee80211_mgmt *pMgmt_frame;
1660 v_U8_t *pIe=NULL;
1661 v_U16_t capab_info;
1662 eCsrAuthType RSNAuthType;
1663 eCsrEncryptionType RSNEncryptType;
1664 eCsrEncryptionType mcRSNEncryptType;
1665 int status = VOS_STATUS_SUCCESS;
1666 tpWLAN_SAPEventCB pSapEventCallback;
1667 hdd_hostapd_state_t *pHostapdState;
1668 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1669 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301670 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001671 struct qc_mac_acl_entry *acl_entry = NULL;
1672 v_SINT_t i;
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001673 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001674
1675 ENTER();
1676
1677 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1678
1679 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1680
1681 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1682
1683 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1684
1685 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1686
1687 //channel is already set in the set_channel Call back
1688 //pConfig->channel = pCommitConfig->channel;
1689
1690 /*Protection parameter to enable or disable*/
1691 pConfig->protEnabled =
1692 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1693
1694 pConfig->dtim_period = pBeacon->dtim_period;
1695
1696 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1697 pConfig->dtim_period);
1698
1699
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001700 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001701 {
1702 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001703 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001704 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001705 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001706 tANI_BOOLEAN restartNeeded;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001707 pConfig->ieee80211d = 1;
1708 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1709 sme_setRegInfo(hHal, pConfig->countryCode);
1710 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
Jeff Johnson295189b2012-06-20 16:38:30 -07001711 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001712 else
1713 {
1714 pConfig->ieee80211d = 0;
1715 }
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301716 /*
1717 * If auto channel is configured i.e. channel is 0,
1718 * so skip channel validation.
1719 */
1720 if( AUTO_CHANNEL_SELECT != pConfig->channel )
1721 {
1722 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1723 {
1724 hddLog(VOS_TRACE_LEVEL_ERROR,
1725 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1726 return -EINVAL;
1727 }
1728 }
1729 else
1730 {
1731 if(1 != pHddCtx->is_dynamic_channel_range_set)
1732 {
1733 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
1734 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
1735 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
1736 }
1737 pHddCtx->is_dynamic_channel_range_set = 0;
1738 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001739 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001740 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001741 {
1742 pConfig->ieee80211d = 0;
1743 }
1744 pConfig->authType = eSAP_AUTO_SWITCH;
1745
1746 capab_info = pMgmt_frame->u.beacon.capab_info;
1747
1748 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
1749 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1750
1751 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1752
1753 /*Set wps station to configured*/
1754 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1755
1756 if(pIe)
1757 {
1758 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1759 {
1760 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1761 return -EINVAL;
1762 }
1763 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1764 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001765 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001766 /* Check 15 bit of WPS IE as it contain information for wps state
1767 * WPS state
1768 */
1769 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1770 {
1771 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1772 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1773 {
1774 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1775 }
1776 }
1777 }
1778 else
1779 {
1780 pConfig->wps_state = SAP_WPS_DISABLED;
1781 }
1782 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
1783
1784 pConfig->RSNWPAReqIELength = 0;
1785 pConfig->pRSNWPAReqIE = NULL;
1786 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1787 WLAN_EID_RSN);
1788 if(pIe && pIe[1])
1789 {
1790 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1791 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1792 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1793 /* The actual processing may eventually be more extensive than
1794 * this. Right now, just consume any PMKIDs that are sent in
1795 * by the app.
1796 * */
1797 status = hdd_softap_unpackIE(
1798 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1799 &RSNEncryptType,
1800 &mcRSNEncryptType,
1801 &RSNAuthType,
1802 pConfig->pRSNWPAReqIE[1]+2,
1803 pConfig->pRSNWPAReqIE );
1804
1805 if( VOS_STATUS_SUCCESS == status )
1806 {
1807 /* Now copy over all the security attributes you have
1808 * parsed out
1809 * */
1810 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1811 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1812 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1813 = RSNEncryptType;
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05301814 hddLog( LOG1, FL("CSR AuthType = %d, "
Jeff Johnson295189b2012-06-20 16:38:30 -07001815 "EncryptionType = %d mcEncryptionType = %d\n"),
1816 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1817 }
1818 }
1819
1820 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1821 pBeacon->tail, pBeacon->tail_len);
1822
1823 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1824 {
1825 if (pConfig->pRSNWPAReqIE)
1826 {
1827 /*Mixed mode WPA/WPA2*/
1828 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1829 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1830 }
1831 else
1832 {
1833 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1834 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1835 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1836 status = hdd_softap_unpackIE(
1837 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1838 &RSNEncryptType,
1839 &mcRSNEncryptType,
1840 &RSNAuthType,
1841 pConfig->pRSNWPAReqIE[1]+2,
1842 pConfig->pRSNWPAReqIE );
1843
1844 if( VOS_STATUS_SUCCESS == status )
1845 {
1846 /* Now copy over all the security attributes you have
1847 * parsed out
1848 * */
1849 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1850 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1851 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1852 = RSNEncryptType;
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05301853 hddLog( LOG1, FL("CSR AuthType = %d, "
Jeff Johnson295189b2012-06-20 16:38:30 -07001854 "EncryptionType = %d mcEncryptionType = %d\n"),
1855 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1856 }
1857 }
1858 }
1859
Jeff Johnson4416a782013-03-25 14:17:50 -07001860 if (pConfig->RSNWPAReqIELength > sizeof wpaRsnIEdata) {
1861 hddLog( VOS_TRACE_LEVEL_ERROR, "**RSNWPAReqIELength is too large***");
1862 return -EINVAL;
1863 }
1864
Jeff Johnson295189b2012-06-20 16:38:30 -07001865 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1866
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001867#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001868 if (params->ssid != NULL)
1869 {
1870 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1871 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1872 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1873 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1874 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001875#else
1876 if (ssid != NULL)
1877 {
1878 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1879 pConfig->SSIDinfo.ssid.length = ssid_len;
1880 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1881 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1882 }
1883#endif
1884
Jeff Johnson295189b2012-06-20 16:38:30 -07001885 vos_mem_copy(pConfig->self_macaddr.bytes,
1886 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1887
1888 /* default value */
1889 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1890 pConfig->num_accept_mac = 0;
1891 pConfig->num_deny_mac = 0;
1892
1893 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1894 pBeacon->tail, pBeacon->tail_len);
1895
1896 /* pIe for black list is following form:
1897 type : 1 byte
1898 length : 1 byte
1899 OUI : 4 bytes
1900 acl type : 1 byte
1901 no of mac addr in black list: 1 byte
1902 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1903 */
1904 if ((pIe != NULL) && (pIe[1] != 0))
1905 {
1906 pConfig->SapMacaddr_acl = pIe[6];
1907 pConfig->num_deny_mac = pIe[7];
1908 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1909 pIe[6], pIe[7]);
1910 if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
1911 pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
1912 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1913 for (i = 0; i < pConfig->num_deny_mac; i++)
1914 {
1915 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1916 acl_entry++;
1917 }
1918 }
1919 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1920 pBeacon->tail, pBeacon->tail_len);
1921
1922 /* pIe for white list is following form:
1923 type : 1 byte
1924 length : 1 byte
1925 OUI : 4 bytes
1926 acl type : 1 byte
1927 no of mac addr in white list: 1 byte
1928 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1929 */
1930 if ((pIe != NULL) && (pIe[1] != 0))
1931 {
1932 pConfig->SapMacaddr_acl = pIe[6];
1933 pConfig->num_accept_mac = pIe[7];
1934 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
1935 pIe[6], pIe[7]);
1936 if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
1937 pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
1938 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1939 for (i = 0; i < pConfig->num_accept_mac; i++)
1940 {
1941 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1942 acl_entry++;
1943 }
1944 }
1945 wlan_hdd_set_sapHwmode(pHostapdAdapter);
1946
Jeff Johnsone7245742012-09-05 17:12:55 -07001947#ifdef WLAN_FEATURE_11AC
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08001948 /* Overwrite the hostapd setting for HW mode only for 11ac.
1949 * This is valid only if mode is set to 11n in hostapd and either AUTO or 11ac in .ini .
1950 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode) */
1951 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
1952 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
1953 (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
1954 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1955 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07001956 {
1957 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
1958 }
1959#endif
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301960
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001961 if( AUTO_CHANNEL_SELECT != pConfig->channel)
1962 wlan_sap_select_cbmode((WLAN_HDD_GET_CTX(pHostapdAdapter)),pConfig->SapHw_mode,pConfig->channel);
Jeff Johnson295189b2012-06-20 16:38:30 -07001963 // ht_capab is not what the name conveys,this is used for protection bitmap
1964 pConfig->ht_capab =
1965 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
1966
1967 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
1968 {
1969 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
1970 return -EINVAL;
1971 }
1972
1973 //Uapsd Enabled Bit
1974 pConfig->UapsdEnable =
1975 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
1976 //Enable OBSS protection
1977 pConfig->obssProtEnabled =
1978 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
1979
1980 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
1981 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
1982 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
1983 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
1984 (int)pConfig->channel);
1985 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
1986 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
1987 pConfig->authType);
1988 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
1989 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
1990 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
1991 pConfig->protEnabled, pConfig->obssProtEnabled);
1992
1993 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
1994 {
1995 //Bss already started. just return.
1996 //TODO Probably it should update some beacon params.
1997 hddLog( LOGE, "Bss Already started...Ignore the request");
1998 EXIT();
1999 return 0;
2000 }
2001
2002 pConfig->persona = pHostapdAdapter->device_mode;
2003
2004 pSapEventCallback = hdd_hostapd_SAPEventCB;
2005 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
2006 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
2007 {
2008 hddLog(LOGE,FL("SAP Start Bss fail\n"));
2009 return -EINVAL;
2010 }
2011
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002012 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07002013 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
2014
2015 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2016
2017 if (!VOS_IS_STATUS_SUCCESS(status))
2018 {
2019 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2020 ("ERROR: HDD vos wait for single_event failed!!\n"));
2021 VOS_ASSERT(0);
2022 }
2023
2024 //Succesfully started Bss update the state bit.
2025 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
2026
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002027#ifdef WLAN_FEATURE_P2P_DEBUG
2028 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
2029 {
2030 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
2031 {
2032 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
2033 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002034 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002035 }
2036 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
2037 {
2038 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
2039 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002040 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002041 }
2042 }
2043#endif
2044
Jeff Johnson295189b2012-06-20 16:38:30 -07002045 pHostapdState->bCommit = TRUE;
2046 EXIT();
2047
2048 return 0;
2049}
2050
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002051#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002052static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
2053 struct net_device *dev,
2054 struct beacon_parameters *params)
2055{
2056 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2057 int status=VOS_STATUS_SUCCESS;
2058
2059 ENTER();
2060
2061 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
2062
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002063 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2064 {
2065 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2066 "%s:LOGP in Progress. Ignore!!!", __func__);
2067 return -EAGAIN;
2068 }
2069
Jeff Johnson295189b2012-06-20 16:38:30 -07002070 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002071 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002072 )
2073 {
2074 beacon_data_t *old,*new;
2075
2076 old = pAdapter->sessionCtx.ap.beacon;
2077
2078 if (old)
2079 return -EALREADY;
2080
2081 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2082
2083 if(status != VOS_STATUS_SUCCESS)
2084 {
2085 hddLog(VOS_TRACE_LEVEL_FATAL,
2086 "%s:Error!!! Allocating the new beacon\n",__func__);
2087 return -EINVAL;
2088 }
2089
2090 pAdapter->sessionCtx.ap.beacon = new;
2091
2092 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2093 }
2094
2095 EXIT();
2096 return status;
2097}
2098
2099static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
2100 struct net_device *dev,
2101 struct beacon_parameters *params)
2102{
2103 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2104 int status=VOS_STATUS_SUCCESS;
2105
2106 ENTER();
2107
2108 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2109 __func__,pAdapter->device_mode);
2110
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002111 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2112 {
2113 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2114 "%s:LOGP in Progress. Ignore!!!", __func__);
2115 return -EAGAIN;
2116 }
2117
Jeff Johnson295189b2012-06-20 16:38:30 -07002118 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002119 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002120 )
2121 {
2122 beacon_data_t *old,*new;
2123
2124 old = pAdapter->sessionCtx.ap.beacon;
2125
2126 if (!old)
2127 return -ENOENT;
2128
2129 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2130
2131 if(status != VOS_STATUS_SUCCESS) {
2132 hddLog(VOS_TRACE_LEVEL_FATAL,
2133 "%s: Error!!! Allocating the new beacon\n",__func__);
2134 return -EINVAL;
2135 }
2136
2137 pAdapter->sessionCtx.ap.beacon = new;
2138
2139 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2140 }
2141
2142 EXIT();
2143 return status;
2144}
2145
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002146#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
2147
2148#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002149static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
2150 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002151#else
2152static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
2153 struct net_device *dev)
2154#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002155{
2156 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07002157 hdd_context_t *pHddCtx = NULL;
2158 hdd_scaninfo_t *pScanInfo = NULL;
2159 hdd_adapter_t *staAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002160 VOS_STATUS status = 0;
2161
2162 ENTER();
2163
2164 if (NULL == pAdapter)
2165 {
2166 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002167 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002168 return -ENODEV;
2169 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002170
Jeff Johnson4416a782013-03-25 14:17:50 -07002171 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002172 if (NULL == pHddCtx)
2173 {
2174 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002175 "%s: HDD context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002176 return -ENODEV;
2177 }
Jeff Johnson4416a782013-03-25 14:17:50 -07002178 if (pHddCtx->isLogpInProgress)
2179 {
2180 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2181 "%s:LOGP in Progress. Ignore!!!", __func__);
2182 return -EAGAIN;
2183 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002184
2185 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
2186 if (NULL == staAdapter)
2187 {
2188 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
2189 if (NULL == staAdapter)
2190 {
2191 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002192 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002193 return -ENODEV;
2194 }
2195 }
2196
2197 pScanInfo = &pHddCtx->scan_info;
2198
Jeff Johnson4416a782013-03-25 14:17:50 -07002199 if (pHddCtx->isLogpInProgress)
Jeff Johnson295189b2012-06-20 16:38:30 -07002200 {
2201 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2202 return -EAGAIN;
2203 }
2204
2205 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2206
2207 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2208 __func__,pAdapter->device_mode);
2209
Jeff Johnsone7245742012-09-05 17:12:55 -07002210 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
2211 {
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002212 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Jeff Johnsone7245742012-09-05 17:12:55 -07002213 hdd_abort_mac_scan(staAdapter->pHddCtx);
2214 status = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002215 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07002216 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
2217 if (!status)
2218 {
2219 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson902c9832012-12-10 14:28:09 -08002220 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002221 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07002222 VOS_ASSERT(pScanInfo->mScanPending);
2223 return 0;
2224 }
2225 }
2226
Jeff Johnson295189b2012-06-20 16:38:30 -07002227 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002228 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002229 )
2230 {
2231 beacon_data_t *old;
2232
2233 old = pAdapter->sessionCtx.ap.beacon;
2234
2235 if (!old)
2236 return -ENOENT;
2237
Jeff Johnson295189b2012-06-20 16:38:30 -07002238 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002239
2240 mutex_lock(&pHddCtx->sap_lock);
2241 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2242 {
Jeff Johnson4416a782013-03-25 14:17:50 -07002243 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss(pHddCtx->pvosContext) ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07002244 {
2245 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2246
2247 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2248
2249 if (!VOS_IS_STATUS_SUCCESS(status))
2250 {
2251 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2252 ("ERROR: HDD vos wait for single_event failed!!\n"));
2253 VOS_ASSERT(0);
2254 }
2255 }
2256 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2257 }
2258 mutex_unlock(&pHddCtx->sap_lock);
2259
2260 if(status != VOS_STATUS_SUCCESS)
2261 {
2262 hddLog(VOS_TRACE_LEVEL_FATAL,
2263 "%s:Error!!! Stopping the BSS\n",__func__);
2264 return -EINVAL;
2265 }
2266
Jeff Johnson4416a782013-03-25 14:17:50 -07002267 if (ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002268 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
2269 ==eHAL_STATUS_FAILURE)
2270 {
2271 hddLog(LOGE,
2272 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
2273 }
2274
Jeff Johnson4416a782013-03-25 14:17:50 -07002275 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002276 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2277 eANI_BOOLEAN_FALSE) )
2278 {
2279 hddLog(LOGE,
2280 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
2281 }
2282
2283 // Reset WNI_CFG_PROBE_RSP Flags
2284 wlan_hdd_reset_prob_rspies(pAdapter);
2285
2286 pAdapter->sessionCtx.ap.beacon = NULL;
2287 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002288#ifdef WLAN_FEATURE_P2P_DEBUG
2289 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
2290 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
2291 {
2292 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
2293 "GO got removed");
2294 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
2295 }
2296#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002297 }
2298 EXIT();
2299 return status;
2300}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002301
2302#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2303
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302304static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2305 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002306 struct cfg80211_ap_settings *params)
2307{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302308 hdd_adapter_t *pAdapter;
2309 hdd_context_t *pHddCtx;
2310 int status = 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002311
2312 ENTER();
2313
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302314 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002315 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302316 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2317 "%s: Device is Null", __func__);
2318 return -ENODEV;
2319 }
2320
2321 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2322 if (NULL == pAdapter)
2323 {
2324 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2325 "%s: HDD adapter is Null", __func__);
2326 return -ENODEV;
2327 }
2328
2329 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2330 {
2331 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2332 "%s: HDD adapter magic is invalid", __func__);
2333 return -ENODEV;
2334 }
2335
2336 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2337 if (NULL == pHddCtx)
2338 {
2339 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2340 "%s: HDD context is Null", __func__);
2341 return -ENODEV;
2342 }
2343
2344 if (pHddCtx->isLogpInProgress)
2345 {
2346 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2347 "%s: LOGP in Progress. Ignore!!!", __func__);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002348 return -EAGAIN;
2349 }
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302350
2351 if (pHddCtx->isLoadUnloadInProgress)
2352 {
2353 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2354 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
2355 return -EAGAIN;
2356 }
2357
2358 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2359 __func__, pAdapter->device_mode);
2360
2361 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002362 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002363 )
2364 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302365 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002366
2367 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302368
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002369 if (old)
2370 return -EALREADY;
2371
2372 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2373
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302374 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002375 {
2376 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302377 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002378 return -EINVAL;
2379 }
2380 pAdapter->sessionCtx.ap.beacon = new;
Viral Modi3a32cc52013-02-08 11:14:52 -08002381#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2382 wlan_hdd_cfg80211_set_channel(wiphy, dev, params->channel, params->channel_type);
2383#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002384 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2385 params->ssid_len, params->hidden_ssid);
2386 }
2387
2388 EXIT();
2389 return status;
2390}
2391
2392
2393static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
2394 struct net_device *dev,
2395 struct cfg80211_beacon_data *params)
2396{
2397 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2398 int status=VOS_STATUS_SUCCESS;
2399
2400 ENTER();
2401
2402 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2403 __func__, pAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002404 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2405 {
2406 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2407 return -EAGAIN;
2408 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002409
2410 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002411 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002412 )
2413 {
2414 beacon_data_t *old,*new;
2415
2416 old = pAdapter->sessionCtx.ap.beacon;
2417
2418 if (!old)
2419 return -ENOENT;
2420
2421 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2422
2423 if(status != VOS_STATUS_SUCCESS) {
2424 hddLog(VOS_TRACE_LEVEL_FATAL,
2425 "%s: Error!!! Allocating the new beacon\n",__func__);
2426 return -EINVAL;
2427 }
2428
2429 pAdapter->sessionCtx.ap.beacon = new;
2430
2431 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2432 }
2433
2434 EXIT();
2435 return status;
2436}
2437
2438#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2439
Jeff Johnson295189b2012-06-20 16:38:30 -07002440
2441static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2442 struct net_device *dev,
2443 struct bss_parameters *params)
2444{
2445 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2446
2447 ENTER();
2448
2449 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2450 __func__,pAdapter->device_mode);
2451
2452 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002453 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002454 )
2455 {
2456 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2457 * want to update this parameter */
2458 if (-1 != params->ap_isolate)
2459 {
2460 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
2461 }
2462 }
2463
2464 EXIT();
2465 return 0;
2466}
2467
2468/*
2469 * FUNCTION: wlan_hdd_cfg80211_change_iface
2470 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2471 */
2472int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2473 struct net_device *ndev,
2474 enum nl80211_iftype type,
2475 u32 *flags,
2476 struct vif_params *params
2477 )
2478{
2479 struct wireless_dev *wdev;
2480 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2481 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002482 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002483 tCsrRoamProfile *pRoamProfile = NULL;
2484 eCsrRoamBssType LastBSSType;
2485 hdd_config_t *pConfig = pHddCtx->cfg_ini;
2486 eMib_dot11DesiredBssType connectedBssType;
2487 VOS_STATUS status;
2488
2489 ENTER();
2490
2491 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2492 {
2493 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2494 return -EAGAIN;
2495 }
2496
2497 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2498 __func__, pAdapter->device_mode);
2499
2500 wdev = ndev->ieee80211_ptr;
2501
2502#ifdef WLAN_BTAMP_FEATURE
2503 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2504 (NL80211_IFTYPE_ADHOC == type)||
2505 (NL80211_IFTYPE_AP == type)||
2506 (NL80211_IFTYPE_P2P_GO == type))
2507 {
2508 pHddCtx->isAmpAllowed = VOS_FALSE;
2509 // stop AMP traffic
2510 status = WLANBAP_StopAmp();
2511 if(VOS_STATUS_SUCCESS != status )
2512 {
2513 pHddCtx->isAmpAllowed = VOS_TRUE;
2514 hddLog(VOS_TRACE_LEVEL_FATAL,
2515 "%s: Failed to stop AMP", __func__);
2516 return -EINVAL;
2517 }
2518 }
2519#endif //WLAN_BTAMP_FEATURE
2520 /* Reset the current device mode bit mask*/
2521 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2522
2523 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07002524 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002525 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002526 )
2527 {
2528 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2529 pRoamProfile = &pWextState->roamProfile;
2530 LastBSSType = pRoamProfile->BSSType;
2531
2532 switch (type)
2533 {
2534 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002535 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002536 hddLog(VOS_TRACE_LEVEL_INFO,
2537 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2538 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002539#ifdef WLAN_FEATURE_11AC
2540 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2541 {
2542 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2543 }
2544#endif
2545 pRoamProfile->phyMode =
2546 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002547 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002548 //Check for sub-string p2p to confirm its a p2p interface
2549 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002550 {
2551 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2552 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2553 }
2554 else
2555 {
2556 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002557 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002558 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002559 break;
2560 case NL80211_IFTYPE_ADHOC:
2561 hddLog(VOS_TRACE_LEVEL_INFO,
2562 "%s: setting interface Type to ADHOC", __func__);
2563 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2564 pRoamProfile->phyMode =
2565 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
2566 wdev->iftype = type;
2567 break;
2568
2569 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002570 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002571 {
2572 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2573 "%s: setting interface Type to %s", __func__,
2574 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2575
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002576 //Cancel any remain on channel for GO mode
2577 if (NL80211_IFTYPE_P2P_GO == type)
2578 {
2579 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2580 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002581 if (NL80211_IFTYPE_AP == type)
2582 {
2583 /* As Loading WLAN Driver one interface being created for p2p device
2584 * address. This will take one HW STA and the max number of clients
2585 * that can connect to softAP will be reduced by one. so while changing
2586 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2587 * interface as it is not required in SoftAP mode.
2588 */
2589
2590 // Get P2P Adapter
2591 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2592
2593 if (pP2pAdapter)
2594 {
2595 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2596 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2597 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2598 }
2599 }
2600
Jeff Johnson295189b2012-06-20 16:38:30 -07002601 //De-init the adapter.
2602 hdd_stop_adapter( pHddCtx, pAdapter );
2603 hdd_deinit_adapter( pHddCtx, pAdapter );
2604 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
Jeff Johnson295189b2012-06-20 16:38:30 -07002605 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2606 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002607
2608 //Disable BMPS and IMPS if enabled
2609 //before starting Go
2610 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2611 {
2612 if(VOS_STATUS_E_FAILURE ==
2613 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2614 {
2615 //Fail to Exit BMPS
2616 VOS_ASSERT(0);
2617 }
2618 }
2619
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002620 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2621 (pConfig->apRandomBssidEnabled))
2622 {
2623 /* To meet Android requirements create a randomized
2624 MAC address of the form 02:1A:11:Fx:xx:xx */
2625 get_random_bytes(&ndev->dev_addr[3], 3);
2626 ndev->dev_addr[0] = 0x02;
2627 ndev->dev_addr[1] = 0x1A;
2628 ndev->dev_addr[2] = 0x11;
2629 ndev->dev_addr[3] |= 0xF0;
2630 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2631 VOS_MAC_ADDR_SIZE);
2632 pr_info("wlan: Generated HotSpot BSSID "
2633 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2634 ndev->dev_addr[0],
2635 ndev->dev_addr[1],
2636 ndev->dev_addr[2],
2637 ndev->dev_addr[3],
2638 ndev->dev_addr[4],
2639 ndev->dev_addr[5]);
2640 }
2641
Jeff Johnson295189b2012-06-20 16:38:30 -07002642 hdd_set_ap_ops( pAdapter->dev );
2643
2644 status = hdd_init_ap_mode(pAdapter);
2645 if(status != VOS_STATUS_SUCCESS)
2646 {
2647 hddLog(VOS_TRACE_LEVEL_FATAL,
2648 "%s: Error initializing the ap mode", __func__);
2649 return -EINVAL;
2650 }
2651 hdd_set_conparam(1);
2652
Jeff Johnson295189b2012-06-20 16:38:30 -07002653 /*interface type changed update in wiphy structure*/
2654 if(wdev)
2655 {
2656 wdev->iftype = type;
2657 pHddCtx->change_iface = type;
2658 }
2659 else
2660 {
2661 hddLog(VOS_TRACE_LEVEL_ERROR,
2662 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2663 return -EINVAL;
2664 }
2665 goto done;
2666 }
2667
2668 default:
2669 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2670 __func__);
2671 return -EOPNOTSUPP;
2672 }
2673 }
2674 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002675 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002676 )
2677 {
2678 switch(type)
2679 {
2680 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002681 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002682 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002683 hdd_stop_adapter( pHddCtx, pAdapter );
2684 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002685 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002686 //Check for sub-string p2p to confirm its a p2p interface
2687 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002688 {
2689 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2690 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2691 }
2692 else
2693 {
2694 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002695 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002696 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002697 hdd_set_conparam(0);
2698 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002699 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2700 hdd_set_station_ops( pAdapter->dev );
2701 status = hdd_init_station_mode( pAdapter );
2702 if( VOS_STATUS_SUCCESS != status )
2703 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002704 /* In case of JB, for P2P-GO, only change interface will be called,
2705 * This is the right place to enable back bmps_imps()
2706 */
2707 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002708 goto done;
2709 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002710 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002711 wdev->iftype = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002712 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2713 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07002714 goto done;
2715 default:
2716 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2717 __func__);
2718 return -EOPNOTSUPP;
2719
2720 }
2721
2722 }
2723 else
2724 {
2725 return -EOPNOTSUPP;
2726 }
2727
2728
2729 if(pRoamProfile)
2730 {
2731 if ( LastBSSType != pRoamProfile->BSSType )
2732 {
2733 /*interface type changed update in wiphy structure*/
2734 wdev->iftype = type;
2735
2736 /*the BSS mode changed, We need to issue disconnect
2737 if connected or in IBSS disconnect state*/
2738 if ( hdd_connGetConnectedBssType(
2739 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2740 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2741 {
2742 /*need to issue a disconnect to CSR.*/
2743 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2744 if( eHAL_STATUS_SUCCESS ==
2745 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2746 pAdapter->sessionId,
2747 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2748 {
2749 wait_for_completion_interruptible_timeout(
2750 &pAdapter->disconnect_comp_var,
2751 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2752 }
2753 }
2754 }
2755 }
2756
2757done:
2758 /*set bitmask based on updated value*/
2759 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
2760#ifdef WLAN_BTAMP_FEATURE
2761 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
2762 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2763 {
2764 //we are ok to do AMP
2765 pHddCtx->isAmpAllowed = VOS_TRUE;
2766 }
2767#endif //WLAN_BTAMP_FEATURE
2768 EXIT();
2769 return 0;
2770}
2771
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002772#ifdef FEATURE_WLAN_TDLS
2773static int wlan_hdd_tdls_add_station(struct wiphy *wiphy,
2774 struct net_device *dev, u8 *mac, bool update, tCsrStaParams *StaParams)
2775{
2776 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2777 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2778 VOS_STATUS status;
2779
2780 ENTER();
2781
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05302782 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002783 {
2784 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2785 "Invalid arguments");
2786 return -EINVAL;
2787 }
Hoonki Lee27511902013-03-14 18:19:06 -07002788
2789 if ((eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) ||
2790 (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode))
2791 {
2792 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2793 "%s: TDLS mode is disabled OR not enabled in FW."
2794 MAC_ADDRESS_STR " Request declined.",
2795 __func__, MAC_ADDR_ARRAY(mac));
2796 return -ENOTSUPP;
2797 }
2798
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002799 if (pHddCtx->isLogpInProgress)
2800 {
2801 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2802 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07002803 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002804 return -EBUSY;
2805 }
2806
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002807 /* when self is on-going, we dont' want to change link_status */
2808 if ((0 == update) && wlan_hdd_tdls_is_peer_progress(pAdapter, mac))
2809 {
2810 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2811 "%s: " MAC_ADDRESS_STR
2812 " TDLS setup is ongoing. Request declined.",
2813 __func__, MAC_ADDR_ARRAY(mac));
2814 return -EPERM;
2815 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002816 /* when self is not on-ongoing, we don't want to allow change_station */
2817 if ((1 == update) && !wlan_hdd_tdls_is_peer_progress(pAdapter, mac))
2818 {
2819 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2820 "%s: " MAC_ADDRESS_STR
2821 " TDLS is not connecting. change station declined.",
2822 __func__, MAC_ADDR_ARRAY(mac));
2823 return -EPERM;
2824 }
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002825
2826 /* when others are on-going, we want to change link_status to idle */
Hoonki Leefb8df672013-04-10 18:20:34 -07002827 if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, mac, TRUE, TRUE))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002828 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002829 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2830 "%s: " MAC_ADDRESS_STR
2831 " TDLS setup is ongoing. Request declined.",
2832 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002833 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002834 }
2835
2836 /* first to check if we reached to maximum supported TDLS peer.
2837 TODO: for now, return -EPERM looks working fine,
2838 but need to check if any other errno fit into this category.*/
2839 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
2840 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002841 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2842 "%s: " MAC_ADDRESS_STR
2843 " TDLS Max peer already connected. Request declined.",
2844 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002845 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002846 }
2847 else
2848 {
2849 hddTdlsPeer_t *pTdlsPeer;
2850 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002851 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002852 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002853 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2854 "%s: " MAC_ADDRESS_STR " already connected. Request declined.",
2855 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002856 return -EPERM;
2857 }
2858 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002859 if (0 == update)
2860 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_CONNECTING);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002861
Jeff Johnsond75fe012013-04-06 10:53:06 -07002862 /* debug code */
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05302863 if (NULL != StaParams)
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002864 {
2865 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2866 "%s: TDLS Peer Parameters.", __func__);
Hoonki Lee66b75f32013-04-16 18:30:07 -07002867 if(StaParams->htcap_present)
2868 {
2869 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2870 "ht_capa->cap_info: %0x", StaParams->HTCap.capInfo);
2871 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2872 "ht_capa->extended_capabilities: %0x",
2873 StaParams->HTCap.extendedHtCapInfo);
2874 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002875 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2876 "params->capability: %0x",StaParams->capability);
2877 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2878 "params->ext_capab_len: %0x",StaParams->extn_capability);
Hoonki Lee66b75f32013-04-16 18:30:07 -07002879 if(StaParams->vhtcap_present)
2880 {
2881 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2882 "rxMcsMap %x rxHighest %x txMcsMap %x txHighest %x",
2883 StaParams->VHTCap.suppMcs.rxMcsMap, StaParams->VHTCap.suppMcs.rxHighest,
2884 StaParams->VHTCap.suppMcs.txMcsMap, StaParams->VHTCap.suppMcs.txHighest);
2885 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002886 {
2887 int i = 0;
2888 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "Supported rates:");
2889 for (i = 0; i < sizeof(StaParams->supported_rates); i++)
2890 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2891 "[%d]: %x ", i, StaParams->supported_rates[i]);
2892 }
Jeff Johnsond75fe012013-04-06 10:53:06 -07002893 } /* end debug code */
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05302894 else if ((1 == update) && (NULL == StaParams))
2895 {
2896 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2897 "%s : update is true, but staParams is NULL. Error!", __func__);
2898 return -EPERM;
2899 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002900
2901 INIT_COMPLETION(pAdapter->tdls_add_station_comp);
2902
2903 if (!update)
2904 {
2905 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
2906 pAdapter->sessionId, mac);
2907 }
2908 else
2909 {
2910 status = sme_ChangeTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
2911 pAdapter->sessionId, mac, StaParams);
2912 }
2913
2914 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_add_station_comp,
2915 msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
2916
2917 if (!status)
2918 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002919 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002920 "%s: timeout waiting for tdls add station indication",
2921 __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002922 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002923 }
2924 if ( eHAL_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus)
2925 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002926 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002927 "%s: Add Station is unsucessful", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002928 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002929 }
2930
2931 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07002932
2933error:
2934 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
2935 return -EPERM;
2936
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002937}
2938#endif
2939
Jeff Johnson295189b2012-06-20 16:38:30 -07002940static int wlan_hdd_change_station(struct wiphy *wiphy,
2941 struct net_device *dev,
2942 u8 *mac,
2943 struct station_parameters *params)
2944{
2945 VOS_STATUS status = VOS_STATUS_SUCCESS;
2946 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2947 v_MACADDR_t STAMacAddress;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002948#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002949 tCsrStaParams StaParams = {0};
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002950 tANI_U8 isBufSta = 0;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002951#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07002952 ENTER();
2953
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002954 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2955 {
2956 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2957 "%s:LOGP in Progress. Ignore!!!", __func__);
2958 return -EAGAIN;
2959 }
2960
Jeff Johnson295189b2012-06-20 16:38:30 -07002961 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
2962
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002963 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2964 || (pAdapter->device_mode == WLAN_HDD_P2P_GO))
Jeff Johnson295189b2012-06-20 16:38:30 -07002965 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002966 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
Jeff Johnson295189b2012-06-20 16:38:30 -07002967 {
2968 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
2969 WLANTL_STA_AUTHENTICATED);
2970
2971 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002972 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002973 return -EINVAL;
2974 }
2975 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002976#ifdef FEATURE_WLAN_TDLS
Hoonki Leea6d49be2013-04-05 09:43:25 -07002977 else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2978 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) {
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002979 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
2980 StaParams.capability = params->capability;
2981 StaParams.uapsd_queues = params->uapsd_queues;
2982 StaParams.max_sp = params->max_sp;
2983
2984 if (0 != params->ext_capab_len)
2985 vos_mem_copy(StaParams.extn_capability, params->ext_capab,
2986 sizeof(StaParams.extn_capability));
2987
2988 if (NULL != params->ht_capa)
Hoonki Lee66b75f32013-04-16 18:30:07 -07002989 {
2990 StaParams.htcap_present = 1;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002991 vos_mem_copy(&StaParams.HTCap, params->ht_capa, sizeof(tSirHTCap));
Hoonki Lee66b75f32013-04-16 18:30:07 -07002992 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002993
2994 StaParams.supported_rates_len = params->supported_rates_len;
2995
2996 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
2997 * The supported_rates array , for all the structures propogating till Add Sta
2998 * to the firmware has to be modified , if the supplicant (ieee80211) is
2999 * modified to send more rates.
3000 */
3001
3002 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
3003 */
3004 if (StaParams.supported_rates_len > SIR_MAC_MAX_SUPP_RATES)
3005 StaParams.supported_rates_len = SIR_MAC_MAX_SUPP_RATES;
3006
3007 if (0 != StaParams.supported_rates_len) {
3008 int i = 0;
3009 vos_mem_copy(StaParams.supported_rates, params->supported_rates,
3010 StaParams.supported_rates_len);
3011 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3012 "Supported Rates with Length %d", StaParams.supported_rates_len);
3013 for (i=0; i < StaParams.supported_rates_len; i++)
3014 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3015 "[%d]: %0x", i, StaParams.supported_rates[i]);
3016 }
3017
3018 if (NULL != params->vht_capa)
Hoonki Lee66b75f32013-04-16 18:30:07 -07003019 {
3020 StaParams.vhtcap_present = 1;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003021 vos_mem_copy(&StaParams.VHTCap, params->vht_capa, sizeof(tSirVHTCap));
Hoonki Lee66b75f32013-04-16 18:30:07 -07003022 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003023
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003024 if (0 != params->ext_capab_len ) {
3025 /*Define A Macro : TODO Sunil*/
3026 if ((1<<4) & StaParams.extn_capability[3]) {
3027 isBufSta = 1;
3028 }
3029 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003030 //status = wlan_hdd_tdls_set_peer_caps( mac, params->uapsd_queues,
3031 // params->max_sp, isBufSta);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003032 //if (VOS_STATUS_SUCCESS != status) {
3033 // VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3034 // "%s: wlan_hdd_tdls_set_peer_caps failed!", __func__);
3035 // return -EINVAL;
3036 //}
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003037 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 1, &StaParams);
3038
3039 if (VOS_STATUS_SUCCESS != status) {
3040 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3041 "%s: sme_ChangeTdlsPeerSta failed!", __func__);
3042 return -EINVAL;
3043 }
3044 }
3045 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003046#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003047
Jeff Johnsone7245742012-09-05 17:12:55 -07003048 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003049 return status;
3050}
3051
3052/*
3053 * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
3054 * This function is used to get peer station index in IBSS mode
3055 */
3056static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
3057{
3058 u8 idx = 0;
3059 u8 temp[VOS_MAC_ADDR_SIZE] = {0};
3060 ENTER();
3061 memset(temp, 0, VOS_MAC_ADDR_SIZE);
3062 for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
3063 {
3064 if ( (0 !=
3065 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
3066 && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
3067 temp, VOS_MAC_ADDR_SIZE)
3068 )
3069 {
3070 return idx;
3071 }
3072 }
3073 return idx;
3074}
3075
3076
3077/*
3078 * FUNCTION: wlan_hdd_cfg80211_add_key
3079 * This function is used to initialize the key information
3080 */
3081#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003082static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003083 struct net_device *ndev,
3084 u8 key_index, bool pairwise,
3085 const u8 *mac_addr,
3086 struct key_params *params
3087 )
3088#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003089static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003090 struct net_device *ndev,
3091 u8 key_index, const u8 *mac_addr,
3092 struct key_params *params
3093 )
3094#endif
3095{
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003096 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003097 tCsrRoamSetKey setKey;
3098 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3099 int status = 0;
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003100 v_U32_t roamId= 0xFF;
3101 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003102 hdd_hostapd_state_t *pHostapdState;
3103 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003104 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07003105
3106 ENTER();
3107
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003108 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3109 {
3110 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3111 "%s:LOGP in Progress. Ignore!!!", __func__);
3112 return -EAGAIN;
3113 }
3114
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003115 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
3116 __func__, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003117
3118 if (CSR_MAX_NUM_KEY <= key_index)
3119 {
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003120 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003121 key_index);
3122
3123 return -EINVAL;
3124 }
3125
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003126 if (CSR_MAX_KEY_LEN < params->key_len)
3127 {
3128 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key length %d", __func__,
3129 params->key_len);
3130
3131 return -EINVAL;
3132 }
3133
3134 hddLog(VOS_TRACE_LEVEL_INFO,
3135 "%s: called with key index = %d & key length %d",
3136 __func__, key_index, params->key_len);
Jeff Johnson295189b2012-06-20 16:38:30 -07003137
3138 /*extract key idx, key len and key*/
3139 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3140 setKey.keyId = key_index;
3141 setKey.keyLength = params->key_len;
3142 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
3143
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003144 switch (params->cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07003145 {
3146 case WLAN_CIPHER_SUITE_WEP40:
3147 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
3148 break;
3149
3150 case WLAN_CIPHER_SUITE_WEP104:
3151 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
3152 break;
3153
3154 case WLAN_CIPHER_SUITE_TKIP:
3155 {
3156 u8 *pKey = &setKey.Key[0];
3157 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
3158
3159 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
3160
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003161 /*Supplicant sends the 32bytes key in this order
Jeff Johnson295189b2012-06-20 16:38:30 -07003162
3163 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003164 | Tk1 |TX-MIC | RX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003165 |--------------|----------|----------|
3166 <---16bytes---><--8bytes--><--8bytes-->
3167
3168 */
3169 /*Sme expects the 32 bytes key to be in the below order
3170
3171 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003172 | Tk1 |RX-MIC | TX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003173 |--------------|----------|----------|
3174 <---16bytes---><--8bytes--><--8bytes-->
3175 */
3176 /* Copy the Temporal Key 1 (TK1) */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003177 vos_mem_copy(pKey, params->key, 16);
Jeff Johnson295189b2012-06-20 16:38:30 -07003178
3179 /*Copy the rx mic first*/
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003180 vos_mem_copy(&pKey[16], &params->key[24], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003181
3182 /*Copy the tx mic */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003183 vos_mem_copy(&pKey[24], &params->key[16], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003184
3185
3186 break;
3187 }
3188
3189 case WLAN_CIPHER_SUITE_CCMP:
3190 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
3191 break;
3192
3193#ifdef FEATURE_WLAN_WAPI
3194 case WLAN_CIPHER_SUITE_SMS4:
3195 {
3196 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3197 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
3198 params->key, params->key_len);
3199 return 0;
3200 }
3201#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003202
Jeff Johnson295189b2012-06-20 16:38:30 -07003203#ifdef FEATURE_WLAN_CCX
3204 case WLAN_CIPHER_SUITE_KRK:
3205 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
3206 break;
3207#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003208
3209#ifdef WLAN_FEATURE_11W
3210 case WLAN_CIPHER_SUITE_AES_CMAC:
3211 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
Chet Lanctot3b5158a2013-03-31 16:45:21 -07003212 break;
Chet Lanctot186b5732013-03-18 10:26:30 -07003213#endif
3214
Jeff Johnson295189b2012-06-20 16:38:30 -07003215 default:
3216 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
3217 __func__, params->cipher);
3218 return -EOPNOTSUPP;
3219 }
3220
3221 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
3222 __func__, setKey.encType);
3223
3224
3225
3226 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003227 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07003228 )
3229 {
3230
3231
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003232 if (
Jeff Johnson295189b2012-06-20 16:38:30 -07003233#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3234 (!pairwise)
3235#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003236 (!mac_addr || is_broadcast_ether_addr(mac_addr))
Jeff Johnson295189b2012-06-20 16:38:30 -07003237#endif
3238 )
3239 {
3240 /* set group key*/
3241 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson1250df42012-12-10 14:31:52 -08003242 "%s- %d: setting Broadcast key",
Jeff Johnson295189b2012-06-20 16:38:30 -07003243 __func__, __LINE__);
3244 setKey.keyDirection = eSIR_RX_ONLY;
3245 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3246 }
3247 else
3248 {
3249 /* set pairwise key*/
3250 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3251 "%s- %d: setting pairwise key",
3252 __func__, __LINE__);
3253 setKey.keyDirection = eSIR_TX_RX;
3254 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3255 }
3256
3257 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003258 if( pHostapdState->bssState == BSS_START )
3259 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003260 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3261
3262 if ( status != eHAL_STATUS_SUCCESS )
3263 {
3264 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3265 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3266 __LINE__, status );
3267 }
3268 }
3269
3270 /* Saving WEP keys */
3271 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
3272 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
3273 {
3274 //Save the wep key in ap context. Issue setkey after the BSS is started.
3275 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3276 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
3277 }
3278 else
3279 {
3280 //Save the key in ap context. Issue setkey after the BSS is started.
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003281 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003282 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
3283 }
3284 }
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003285 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
3286 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) )
Jeff Johnson295189b2012-06-20 16:38:30 -07003287 {
3288 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3289 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3290
3291 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
3292
Venkata Prathyusha Kuntupalliee2ce712013-01-17 14:09:24 -08003293 pWextState->roamProfile.Keys.defaultIndex = key_index;
3294
3295
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003296 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07003297 params->key, params->key_len);
3298
3299 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3300
3301 if (!( ( IW_AUTH_KEY_MGMT_802_1X
3302 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
3303 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3304 )
3305 &&
3306 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3307 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3308 )
3309 )
3310 {
3311 /* in case of static WEP, macaddr/bssid is not coming from nl80211
3312 * interface, copy bssid for pairwise key and group macaddr for
3313 * group key initialization*/
3314
3315 tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
3316
3317 pWextState->roamProfile.negotiatedUCEncryptionType =
3318 pHddStaCtx->conn_info.ucEncryptionType =
3319 ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
3320 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
3321 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
3322
3323
3324 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3325 "%s: Negotiated encryption type %d", __func__,
3326 pWextState->roamProfile.negotiatedUCEncryptionType);
3327
3328 sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
3329 &pWextState->roamProfile, true);
3330 setKey.keyLength = 0;
3331 setKey.keyDirection = eSIR_TX_RX;
3332
3333#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3334 if (pairwise)
3335 {
3336#endif
3337 if (mac_addr)
3338 {
3339 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3340 }
3341 else
3342 {
3343 /* macaddr is NULL, set the peerMac to bssId in case of BSS,
3344 * and peerMacAddress in case of IBSS*/
3345 if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
3346 {
3347 u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
3348 if (HDD_MAX_NUM_IBSS_STA != staidx)
3349 {
3350 vos_mem_copy(setKey.peerMac,
3351 &pHddStaCtx->conn_info.peerMacAddress[staidx],
3352 WNI_CFG_BSSID_LEN);
3353
3354 }
3355 else
3356 {
3357 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
3358 __func__);
3359 return -EOPNOTSUPP;
3360 }
3361 }
3362 else
3363 {
3364 vos_mem_copy(setKey.peerMac,
3365 &pHddStaCtx->conn_info.bssId[0],
3366 WNI_CFG_BSSID_LEN);
3367 }
3368 }
3369#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3370 }
3371 else
3372 {
3373 /* set group key*/
3374 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3375 "%s- %d: setting Group key",
3376 __func__, __LINE__);
3377 setKey.keyDirection = eSIR_RX_ONLY;
3378 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3379 }
3380#endif
3381 }
3382 else if (
3383#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3384 (!pairwise)
3385#else
3386 (!mac_addr || is_broadcast_ether_addr(mac_addr))
3387#endif
3388 )
3389 {
3390 /* set group key*/
3391 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3392 "%s- %d: setting Group key",
3393 __func__, __LINE__);
3394 setKey.keyDirection = eSIR_RX_ONLY;
3395 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3396 }
3397 else
3398 {
3399 /* set pairwise key*/
3400 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3401 "%s- %d: setting pairwise key",
3402 __func__, __LINE__);
3403 setKey.keyDirection = eSIR_TX_RX;
3404 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3405 }
3406
3407 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3408 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3409 __func__, setKey.peerMac[0], setKey.peerMac[1],
3410 setKey.peerMac[2], setKey.peerMac[3],
3411 setKey.peerMac[4], setKey.peerMac[5],
3412 setKey.keyDirection);
3413
3414 vos_status = wlan_hdd_check_ula_done(pAdapter);
3415
3416 if ( vos_status != VOS_STATUS_SUCCESS )
3417 {
3418 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3419 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
3420 __LINE__, vos_status );
3421
3422 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3423
3424 return -EINVAL;
3425
3426 }
3427
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003428#ifdef WLAN_FEATURE_VOWIFI_11R
3429 /* The supplicant may attempt to set the PTK once pre-authentication is done.
3430 Save the key in the UMAC and include it in the ADD BSS request */
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003431 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303432 if( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_WAIT )
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003433 {
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303434 return -EINVAL;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003435 }
3436#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07003437
3438 /* issue set key request to SME*/
3439 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3440 pAdapter->sessionId, &setKey, &roamId );
3441
3442 if ( 0 != status )
3443 {
3444 hddLog(VOS_TRACE_LEVEL_ERROR,
3445 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3446 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3447 return -EINVAL;
3448 }
3449
3450
3451 /* in case of IBSS as there was no information available about WEP keys during
3452 * IBSS join, group key intialized with NULL key, so re-initialize group key
3453 * with correct value*/
3454 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
3455 !( ( IW_AUTH_KEY_MGMT_802_1X
3456 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
3457 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3458 )
3459 &&
3460 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3461 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3462 )
3463 )
3464 {
3465 setKey.keyDirection = eSIR_RX_ONLY;
3466 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3467
3468 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3469 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3470 __func__, setKey.peerMac[0], setKey.peerMac[1],
3471 setKey.peerMac[2], setKey.peerMac[3],
3472 setKey.peerMac[4], setKey.peerMac[5],
3473 setKey.keyDirection);
3474
3475 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3476 pAdapter->sessionId, &setKey, &roamId );
3477
3478 if ( 0 != status )
3479 {
3480 hddLog(VOS_TRACE_LEVEL_ERROR,
3481 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
3482 __func__, status);
3483 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3484 return -EINVAL;
3485 }
3486 }
3487 }
3488
3489 return 0;
3490}
3491
3492/*
3493 * FUNCTION: wlan_hdd_cfg80211_get_key
3494 * This function is used to get the key information
3495 */
3496#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3497static int wlan_hdd_cfg80211_get_key(
3498 struct wiphy *wiphy,
3499 struct net_device *ndev,
3500 u8 key_index, bool pairwise,
3501 const u8 *mac_addr, void *cookie,
3502 void (*callback)(void *cookie, struct key_params*)
3503 )
3504#else
3505static int wlan_hdd_cfg80211_get_key(
3506 struct wiphy *wiphy,
3507 struct net_device *ndev,
3508 u8 key_index, const u8 *mac_addr, void *cookie,
3509 void (*callback)(void *cookie, struct key_params*)
3510 )
3511#endif
3512{
3513 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3514 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3515 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
3516 struct key_params params;
3517
3518 ENTER();
3519
3520 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3521 __func__,pAdapter->device_mode);
3522
3523 memset(&params, 0, sizeof(params));
3524
3525 if (CSR_MAX_NUM_KEY <= key_index)
3526 {
3527 return -EINVAL;
3528 }
3529
3530 switch(pRoamProfile->EncryptionType.encryptionType[0])
3531 {
3532 case eCSR_ENCRYPT_TYPE_NONE:
3533 params.cipher = IW_AUTH_CIPHER_NONE;
3534 break;
3535
3536 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3537 case eCSR_ENCRYPT_TYPE_WEP40:
3538 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3539 break;
3540
3541 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3542 case eCSR_ENCRYPT_TYPE_WEP104:
3543 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3544 break;
3545
3546 case eCSR_ENCRYPT_TYPE_TKIP:
3547 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3548 break;
3549
3550 case eCSR_ENCRYPT_TYPE_AES:
3551 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3552 break;
3553
3554 default:
3555 params.cipher = IW_AUTH_CIPHER_NONE;
3556 break;
3557 }
3558
3559 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3560 params.seq_len = 0;
3561 params.seq = NULL;
3562 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3563 callback(cookie, &params);
3564 return 0;
3565}
3566
3567/*
3568 * FUNCTION: wlan_hdd_cfg80211_del_key
3569 * This function is used to delete the key information
3570 */
3571#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3572static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3573 struct net_device *ndev,
3574 u8 key_index,
3575 bool pairwise,
3576 const u8 *mac_addr
3577 )
3578#else
3579static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3580 struct net_device *ndev,
3581 u8 key_index,
3582 const u8 *mac_addr
3583 )
3584#endif
3585{
3586 int status = 0;
3587
3588 //This code needs to be revisited. There is sme_removeKey API, we should
3589 //plan to use that. After the change to use correct index in setkey,
3590 //it is observed that this is invalidating peer
3591 //key index whenever re-key is done. This is affecting data link.
3592 //It should be ok to ignore del_key.
3593#if 0
3594 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3595 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
3596 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3597 tCsrRoamSetKey setKey;
3598 v_U32_t roamId= 0xFF;
3599
3600 ENTER();
3601
3602 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3603 __func__,pAdapter->device_mode);
3604
3605 if (CSR_MAX_NUM_KEY <= key_index)
3606 {
3607 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3608 key_index);
3609
3610 return -EINVAL;
3611 }
3612
3613 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3614 setKey.keyId = key_index;
3615
3616 if (mac_addr)
3617 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3618 else
3619 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3620
3621 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3622
3623 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003624 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07003625 )
3626 {
3627
3628 hdd_hostapd_state_t *pHostapdState =
3629 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3630 if( pHostapdState->bssState == BSS_START)
3631 {
3632 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3633
3634 if ( status != eHAL_STATUS_SUCCESS )
3635 {
3636 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3637 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3638 __LINE__, status );
3639 }
3640 }
3641 }
3642 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003643 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003644 )
3645 {
3646 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3647
3648 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3649
3650 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3651 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
3652 __func__, setKey.peerMac[0], setKey.peerMac[1],
3653 setKey.peerMac[2], setKey.peerMac[3],
3654 setKey.peerMac[4], setKey.peerMac[5]);
3655 if(pAdapter->sessionCtx.station.conn_info.connState ==
3656 eConnectionState_Associated)
3657 {
3658 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3659 pAdapter->sessionId, &setKey, &roamId );
3660
3661 if ( 0 != status )
3662 {
3663 hddLog(VOS_TRACE_LEVEL_ERROR,
3664 "%s: sme_RoamSetKey failure, returned %d",
3665 __func__, status);
3666 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3667 return -EINVAL;
3668 }
3669 }
3670 }
3671#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003672 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003673 return status;
3674}
3675
3676/*
3677 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3678 * This function is used to set the default tx key index
3679 */
3680#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3681static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3682 struct net_device *ndev,
3683 u8 key_index,
3684 bool unicast, bool multicast)
3685#else
3686static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3687 struct net_device *ndev,
3688 u8 key_index)
3689#endif
3690{
3691 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3692 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3693 int status = 0;
3694 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3695
3696 ENTER();
3697
3698 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3699 __func__,pAdapter->device_mode, key_index);
3700
3701 if (CSR_MAX_NUM_KEY <= key_index)
3702 {
3703 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3704 key_index);
3705
3706 return -EINVAL;
3707 }
3708
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003709 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3710 {
3711 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3712 "%s:LOGP in Progress. Ignore!!!", __func__);
3713 return -EAGAIN;
3714 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003715
3716 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003717 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003718 )
3719 {
3720 if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
3721 (eCSR_ENCRYPT_TYPE_TKIP !=
3722 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3723 (eCSR_ENCRYPT_TYPE_AES !=
3724 pWextState->roamProfile.EncryptionType.encryptionType[0])
3725 )
3726 {
3727 /* if default key index is not same as previous one,
3728 * then update the default key index */
3729
3730 tCsrRoamSetKey setKey;
3731 v_U32_t roamId= 0xFF;
3732 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
3733
3734 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
3735 __func__, key_index);
3736
3737 Keys->defaultIndex = (u8)key_index;
3738 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3739 setKey.keyId = key_index;
3740 setKey.keyLength = Keys->KeyLength[key_index];
3741
3742 vos_mem_copy(&setKey.Key[0],
3743 &Keys->KeyMaterial[key_index][0],
3744 Keys->KeyLength[key_index]);
3745
3746 setKey.keyDirection = eSIR_TX_ONLY;
3747
3748 vos_mem_copy(setKey.peerMac,
3749 &pHddStaCtx->conn_info.bssId[0],
3750 WNI_CFG_BSSID_LEN);
3751
3752 setKey.encType =
3753 pWextState->roamProfile.EncryptionType.encryptionType[0];
3754
3755 /* issue set key request */
3756 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3757 pAdapter->sessionId, &setKey, &roamId );
3758
3759 if ( 0 != status )
3760 {
3761 hddLog(VOS_TRACE_LEVEL_ERROR,
3762 "%s: sme_RoamSetKey failed, returned %d", __func__,
3763 status);
3764 return -EINVAL;
3765 }
3766 }
3767 }
3768
3769 /* In SoftAp mode setting key direction for default mode */
3770 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3771 {
3772 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3773 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3774 (eCSR_ENCRYPT_TYPE_AES !=
3775 pWextState->roamProfile.EncryptionType.encryptionType[0])
3776 )
3777 {
3778 /* Saving key direction for default key index to TX default */
3779 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3780 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3781 }
3782 }
3783
3784 return status;
3785}
3786
Jeff Johnson295189b2012-06-20 16:38:30 -07003787/*
3788 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3789 * This function is used to inform the BSS details to nl80211 interface.
3790 */
3791static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3792 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3793{
3794 struct net_device *dev = pAdapter->dev;
3795 struct wireless_dev *wdev = dev->ieee80211_ptr;
3796 struct wiphy *wiphy = wdev->wiphy;
3797 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3798 int chan_no;
3799 int ie_length;
3800 const char *ie;
3801 unsigned int freq;
3802 struct ieee80211_channel *chan;
3803 int rssi = 0;
3804 struct cfg80211_bss *bss = NULL;
3805
3806 ENTER();
3807
3808 if( NULL == pBssDesc )
3809 {
3810 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3811 return bss;
3812 }
3813
3814 chan_no = pBssDesc->channelId;
3815 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3816 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3817
3818 if( NULL == ie )
3819 {
3820 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3821 return bss;
3822 }
3823
3824#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3825 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3826 {
3827 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3828 }
3829 else
3830 {
3831 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3832 }
3833#else
3834 freq = ieee80211_channel_to_frequency(chan_no);
3835#endif
3836
3837 chan = __ieee80211_get_channel(wiphy, freq);
3838
3839 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3840 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3841 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3842 if (bss == NULL)
3843 {
3844 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3845
3846 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3847 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3848 pBssDesc->capabilityInfo,
3849 pBssDesc->beaconInterval, ie, ie_length,
3850 rssi, GFP_KERNEL ));
3851}
3852 else
3853 {
3854 return bss;
3855 }
3856}
3857
3858
3859
3860/*
3861 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3862 * This function is used to inform the BSS details to nl80211 interface.
3863 */
3864struct cfg80211_bss*
3865wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3866 tSirBssDescription *bss_desc
3867 )
3868{
3869 /*
3870 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3871 already exists in bss data base of cfg80211 for that particular BSS ID.
3872 Using cfg80211_inform_bss_frame to update the bss entry instead of
3873 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3874 now there is no possibility to get the mgmt(probe response) frame from PE,
3875 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3876 cfg80211_inform_bss_frame.
3877 */
3878 struct net_device *dev = pAdapter->dev;
3879 struct wireless_dev *wdev = dev->ieee80211_ptr;
3880 struct wiphy *wiphy = wdev->wiphy;
3881 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003882#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3883 qcom_ie_age *qie_age = NULL;
3884 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3885#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003886 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003887#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003888 const char *ie =
3889 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3890 unsigned int freq;
3891 struct ieee80211_channel *chan;
3892 struct ieee80211_mgmt *mgmt =
3893 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3894 struct cfg80211_bss *bss_status = NULL;
3895 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3896 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003897#ifdef WLAN_OPEN_SOURCE
3898 struct timespec ts;
3899#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003900
3901 ENTER();
3902
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003903 if (!mgmt)
3904 return NULL;
3905
Jeff Johnson295189b2012-06-20 16:38:30 -07003906 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003907
3908#ifdef WLAN_OPEN_SOURCE
3909 /* Android does not want the timestamp from the frame.
3910 Instead it wants a monotonic increasing value */
3911 get_monotonic_boottime(&ts);
3912 mgmt->u.probe_resp.timestamp =
3913 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3914#else
3915 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003916 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3917 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003918
3919#endif
3920
Jeff Johnson295189b2012-06-20 16:38:30 -07003921 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3922 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003923
3924#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3925 /* GPS Requirement: need age ie per entry. Using vendor specific. */
3926 /* Assuming this is the last IE, copy at the end */
3927 ie_length -=sizeof(qcom_ie_age);
3928 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
3929 qie_age->element_id = QCOM_VENDOR_IE_ID;
3930 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
3931 qie_age->oui_1 = QCOM_OUI1;
3932 qie_age->oui_2 = QCOM_OUI2;
3933 qie_age->oui_3 = QCOM_OUI3;
3934 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
3935 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
3936#endif
3937
Jeff Johnson295189b2012-06-20 16:38:30 -07003938 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3939
3940 mgmt->frame_control |=
3941 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3942
3943#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3944 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3945 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3946 {
3947 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3948 }
3949 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3950 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3951
3952 {
3953 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3954 }
3955 else
3956 {
3957 kfree(mgmt);
3958 return NULL;
3959 }
3960#else
3961 freq = ieee80211_channel_to_frequency(chan_no);
3962#endif
3963 chan = __ieee80211_get_channel(wiphy, freq);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08003964 /*when the band is changed on the fly using the GUI, three things are done
3965 * 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)
3966 * as part of the scan abort, message willbe queued to PE and we proceed with flushing and changinh the band.
3967 * pe will stop the scanning further and report back the results what ever it had till now by calling the call back function.
3968 * if the time between update band and scandone call back is sufficent enough the band change reflects in SME, SME validates the channels
3969 * and discards the channels correponding to previous band and calls back with zero bss results.
3970 * 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
3971 * all the channels correponding to previous band.this is due to race condition.but those channels are invalid to the new band and so
3972 * this function __ieee80211_get_channel will return NULL.Each time we report scan result with this pointer null warning kernel trace is printed.
3973 * if the scan results contain large number of APs continuosly kernel warning trace is printed and it will lead to apps watch dog bark.
3974 * So drop the bss and continue to next bss.
3975 */
3976 if(chan == NULL)
3977 {
3978 hddLog(VOS_TRACE_LEVEL_INFO, "%s chan pointer is NULL", __func__);
Chilam Ngc4244af2013-04-01 15:37:32 -07003979 kfree(mgmt);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08003980 return NULL;
3981 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003982 /*To keep the rssi icon of the connected AP in the scan window
3983 *and the rssi icon of the wireless networks in sync
3984 * */
3985 if (( eConnectionState_Associated ==
3986 pAdapter->sessionCtx.station.conn_info.connState ) &&
3987 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3988 pAdapter->sessionCtx.station.conn_info.bssId,
3989 WNI_CFG_BSSID_LEN)))
3990 {
3991 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3992 rssi = (pAdapter->rssi * 100);
3993 }
3994 else
3995 {
3996 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3997 }
3998
3999 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
4000 frame_len, rssi, GFP_KERNEL);
4001 kfree(mgmt);
4002 return bss_status;
4003}
4004
4005/*
4006 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
4007 * This function is used to update the BSS data base of CFG8011
4008 */
4009struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
4010 tCsrRoamInfo *pRoamInfo
4011 )
4012{
4013 tCsrRoamConnectedProfile roamProfile;
4014 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4015 struct cfg80211_bss *bss = NULL;
4016
4017 ENTER();
4018
4019 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
4020 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
4021
4022 if (NULL != roamProfile.pBssDesc)
4023 {
4024 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
4025 &roamProfile);
4026
4027 if (NULL == bss)
4028 {
4029 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
4030 __func__);
4031 }
4032
4033 sme_RoamFreeConnectProfile(hHal, &roamProfile);
4034 }
4035 else
4036 {
4037 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
4038 __func__);
4039 }
4040 return bss;
4041}
4042
4043/*
4044 * FUNCTION: wlan_hdd_cfg80211_update_bss
4045 */
4046static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
4047 hdd_adapter_t *pAdapter
4048 )
4049{
4050 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4051 tCsrScanResultInfo *pScanResult;
4052 eHalStatus status = 0;
4053 tScanResultHandle pResult;
4054 struct cfg80211_bss *bss_status = NULL;
4055
4056 ENTER();
4057
4058 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4059 {
4060 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
4061 return -EAGAIN;
4062 }
4063
4064 /*
4065 * start getting scan results and populate cgf80211 BSS database
4066 */
4067 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
4068
4069 /* no scan results */
4070 if (NULL == pResult)
4071 {
4072 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
4073 return status;
4074 }
4075
4076 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
4077
4078 while (pScanResult)
4079 {
4080 /*
4081 * cfg80211_inform_bss() is not updating ie field of bss entry, if
4082 * entry already exists in bss data base of cfg80211 for that
4083 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
4084 * bss entry instead of cfg80211_inform_bss, But this call expects
4085 * mgmt packet as input. As of now there is no possibility to get
4086 * the mgmt(probe response) frame from PE, converting bss_desc to
4087 * ieee80211_mgmt(probe response) and passing to c
4088 * fg80211_inform_bss_frame.
4089 * */
4090
4091 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
4092 &pScanResult->BssDescriptor);
4093
4094
4095 if (NULL == bss_status)
4096 {
4097 hddLog(VOS_TRACE_LEVEL_INFO,
4098 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
4099 }
4100 else
4101 {
4102 cfg80211_put_bss(bss_status);
4103 }
4104
4105 pScanResult = sme_ScanResultGetNext(hHal, pResult);
4106 }
4107
4108 sme_ScanResultPurge(hHal, pResult);
4109
4110 return 0;
4111}
4112
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004113void
4114hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
4115{
4116 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004117 "%02X:%02X:%02X:%02X:%02X:%02X\n",
4118 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
4119 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004120} /****** end hddPrintMacAddr() ******/
4121
4122void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004123hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004124{
4125 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004126 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
4127 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
4128 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
4129 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004130} /****** end hddPrintPmkId() ******/
4131
4132//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
4133//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
4134
4135//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
4136//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
4137
4138#define dump_bssid(bssid) \
4139 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004140 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
4141 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
4142 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004143 }
4144
4145#define dump_pmkid(pMac, pmkid) \
4146 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004147 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
4148 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
4149 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004150 }
4151
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07004152#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004153/*
4154 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
4155 * This function is used to notify the supplicant of a new PMKSA candidate.
4156 */
4157int wlan_hdd_cfg80211_pmksa_candidate_notify(
4158 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
4159 int index, bool preauth )
4160{
Jeff Johnsone7245742012-09-05 17:12:55 -07004161#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004162 struct net_device *dev = pAdapter->dev;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004163 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004164
4165 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07004166 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004167
4168 if( NULL == pRoamInfo )
4169 {
4170 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
4171 return -EINVAL;
4172 }
4173
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004174 if (eANI_BOOLEAN_TRUE == hdd_is_okc_mode_enabled(pHddCtx))
4175 {
4176 dump_bssid(pRoamInfo->bssid);
4177 cfg80211_pmksa_candidate_notify(dev, index,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004178 pRoamInfo->bssid, preauth, GFP_KERNEL);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004179 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004180#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004181 return 0;
4182}
4183#endif //FEATURE_WLAN_LFR
4184
Jeff Johnson295189b2012-06-20 16:38:30 -07004185/*
4186 * FUNCTION: hdd_cfg80211_scan_done_callback
4187 * scanning callback function, called after finishing scan
4188 *
4189 */
4190static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
4191 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
4192{
4193 struct net_device *dev = (struct net_device *) pContext;
4194 //struct wireless_dev *wdev = dev->ieee80211_ptr;
4195 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004196 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4197 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004198 struct cfg80211_scan_request *req = NULL;
4199 int ret = 0;
4200
4201 ENTER();
4202
4203 hddLog(VOS_TRACE_LEVEL_INFO,
4204 "%s called with halHandle = %p, pContext = %p,"
4205 "scanID = %d, returned status = %d\n",
4206 __func__, halHandle, pContext, (int) scanId, (int) status);
4207
4208 //Block on scan req completion variable. Can't wait forever though.
4209 ret = wait_for_completion_interruptible_timeout(
4210 &pScanInfo->scan_req_completion_event,
4211 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
4212 if (!ret)
4213 {
4214 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004215 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004216 }
4217
4218 if(pScanInfo->mScanPending != VOS_TRUE)
4219 {
4220 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004221 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004222 }
4223
4224 /* Check the scanId */
4225 if (pScanInfo->scanId != scanId)
4226 {
4227 hddLog(VOS_TRACE_LEVEL_INFO,
4228 "%s called with mismatched scanId pScanInfo->scanId = %d "
4229 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
4230 (int) scanId);
4231 }
4232
Jeff Johnson295189b2012-06-20 16:38:30 -07004233 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
4234 pAdapter);
4235
4236 if (0 > ret)
4237 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
4238
4239
4240 /* If any client wait scan result through WEXT
4241 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004242 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07004243 {
4244 /* The other scan request waiting for current scan finish
4245 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004246 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004247 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004248 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004249 }
4250 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004251 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004252 {
4253 struct net_device *dev = pAdapter->dev;
4254 union iwreq_data wrqu;
4255 int we_event;
4256 char *msg;
4257
4258 memset(&wrqu, '\0', sizeof(wrqu));
4259 we_event = SIOCGIWSCAN;
4260 msg = NULL;
4261 wireless_send_event(dev, we_event, &wrqu, msg);
4262 }
4263 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004264 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004265
4266 /* Get the Scan Req */
4267 req = pAdapter->request;
4268
4269 if (!req)
4270 {
4271 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004272 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07004273 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004274 }
4275
4276 /*
4277 * setting up 0, just in case.
4278 */
4279 req->n_ssids = 0;
4280 req->n_channels = 0;
4281 req->ie = 0;
4282
Jeff Johnson295189b2012-06-20 16:38:30 -07004283 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004284 /* Scan is no longer pending */
4285 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004286
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07004287 /*
4288 * cfg80211_scan_done informing NL80211 about completion
4289 * of scanning
4290 */
4291 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004292 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004293
Jeff Johnsone7245742012-09-05 17:12:55 -07004294allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004295 /* release the wake lock at the end of the scan*/
4296 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004297
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004298 /* Acquire wakelock to handle the case where APP's tries to suspend
4299 * immediatly after the driver gets connect request(i.e after scan)
4300 * from supplicant, this result in app's is suspending and not able
4301 * to process the connect request to AP */
4302 hdd_allow_suspend_timeout(100);
4303
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004304#ifdef FEATURE_WLAN_TDLS
4305 wlan_hdd_tdls_scan_done_callback(pAdapter);
4306#endif
4307
Jeff Johnson295189b2012-06-20 16:38:30 -07004308 EXIT();
4309 return 0;
4310}
4311
4312/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004313 * FUNCTION: hdd_isScanAllowed
4314 * Go through each adapter and check if scan allowed
4315 *
4316 */
4317v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
4318{
4319 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4320 hdd_station_ctx_t *pHddStaCtx = NULL;
4321 hdd_adapter_t *pAdapter = NULL;
4322 VOS_STATUS status = 0;
4323 v_U8_t staId = 0;
4324 v_U8_t *staMac = NULL;
4325
4326 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4327
4328 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4329 {
4330 pAdapter = pAdapterNode->pAdapter;
4331
4332 if( pAdapter )
4333 {
4334 hddLog(VOS_TRACE_LEVEL_INFO,
4335 "%s: Adapter with device mode %d exists",
4336 __func__, pAdapter->device_mode);
4337 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4338 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4339 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
4340 {
4341 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4342 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
4343 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
4344 {
4345 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
4346 hddLog(VOS_TRACE_LEVEL_ERROR,
4347 "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the "
4348 "middle of WPS/EAPOL exchange.", __func__,
4349 staMac[0], staMac[1], staMac[2],
4350 staMac[3], staMac[4], staMac[5]);
4351 return VOS_FALSE;
4352 }
4353 }
4354 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
4355 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
4356 {
4357 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
4358 {
4359 if ((pAdapter->aStaInfo[staId].isUsed) &&
4360 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
4361 {
4362 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
4363
4364 hddLog(VOS_TRACE_LEVEL_ERROR,
4365 "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the "
4366 "middle of WPS/EAPOL exchange.", __func__,
4367 staMac[0], staMac[1], staMac[2],
4368 staMac[3], staMac[4], staMac[5]);
4369 return VOS_FALSE;
4370 }
4371 }
4372 }
4373 }
4374 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4375 pAdapterNode = pNext;
4376 }
4377 hddLog(VOS_TRACE_LEVEL_INFO,
4378 "%s: Scan allowed", __func__);
4379 return VOS_TRUE;
4380}
4381
4382/*
Jeff Johnson295189b2012-06-20 16:38:30 -07004383 * FUNCTION: wlan_hdd_cfg80211_scan
4384 * this scan respond to scan trigger and update cfg80211 scan database
4385 * later, scan dump command can be used to recieve scan results
4386 */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08004387int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
4388#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4389 struct net_device *dev,
4390#endif
4391 struct cfg80211_scan_request *request)
4392{
4393#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4394 struct net_device *dev = request->wdev->netdev;
4395#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004396 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4397 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4398 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4399 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
4400 tCsrScanRequest scanRequest;
4401 tANI_U8 *channelList = NULL, i;
4402 v_U32_t scanId = 0;
4403 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004404 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004405 v_U8_t* pP2pIe = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004406
4407 ENTER();
4408
4409 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4410 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004411
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004412 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004413 (eConnectionState_Connecting ==
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004414 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004415 {
4416 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004417 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
4418 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004419 return -EBUSY;
4420 }
4421
Jeff Johnson295189b2012-06-20 16:38:30 -07004422#ifdef WLAN_BTAMP_FEATURE
4423 //Scan not supported when AMP traffic is on.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004424 if (VOS_TRUE == WLANBAP_AmpSessionOn())
Jeff Johnson295189b2012-06-20 16:38:30 -07004425 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004426 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004427 "%s: No scanning when AMP is on", __func__);
4428 return -EOPNOTSUPP;
4429 }
4430#endif
4431 //Scan on any other interface is not supported.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004432 if (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07004433 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004434 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004435 "%s: Not scanning on device_mode = %d",
4436 __func__, pAdapter->device_mode);
4437 return -EOPNOTSUPP;
4438 }
4439
4440 if (TRUE == pScanInfo->mScanPending)
4441 {
4442 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004443 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07004444 }
4445
4446 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4447 {
4448 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4449 "%s:LOGP in Progress. Ignore!!!", __func__);
4450 return -EAGAIN;
4451 }
4452
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07004453 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
4454 {
4455 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4456 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
4457 return -EAGAIN;
4458 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004459 //Don't Allow Scan and return busy if Remain On
4460 //Channel and action frame is pending
4461 //Otherwise Cancel Remain On Channel and allow Scan
4462 //If no action frame pending
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004463 if (0 != wlan_hdd_check_remain_on_channel(pAdapter))
Jeff Johnson32d95a32012-09-10 13:15:23 -07004464 {
4465 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
4466 return -EBUSY;
4467 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004468#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004469 /* if tdls disagree scan right now, return immediately.
4470 tdls will schedule the scan when scan is allowed. (return SUCCESS)
4471 or will reject the scan if any TDLS is in progress. (return -EBUSY)
4472 */
4473 status = wlan_hdd_tdls_scan_callback (pAdapter,
4474 wiphy,
4475#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4476 dev,
Gopichand Nakkalac3c42b92013-03-20 19:42:34 -07004477#endif
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004478 request);
4479 if(status <= 0)
4480 {
4481 hddLog(VOS_TRACE_LEVEL_INFO, "%s: TDLS Pending %d", __func__, status);
4482 return status;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004483 }
4484#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07004485
Jeff Johnson295189b2012-06-20 16:38:30 -07004486 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
4487 {
4488 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08004489 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004490 return -EAGAIN;
4491 }
4492 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
4493 {
4494 hddLog(VOS_TRACE_LEVEL_WARN,
4495 "%s: MAX TM Level Scan not allowed", __func__);
4496 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4497 return -EBUSY;
4498 }
4499 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4500
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004501 /* Check if scan is allowed at this point of time.
4502 */
4503 if (!hdd_isScanAllowed(pHddCtx))
4504 {
4505 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
4506 return -EBUSY;
4507 }
4508
Jeff Johnson295189b2012-06-20 16:38:30 -07004509 vos_mem_zero( &scanRequest, sizeof(scanRequest));
4510
4511 if (NULL != request)
4512 {
4513 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
4514 (int)request->n_ssids);
4515
4516 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
4517 * Becasue of this, driver is assuming that this is not wildcard scan and so
4518 * is not aging out the scan results.
4519 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07004520 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07004521 {
4522 request->n_ssids = 0;
4523 }
4524
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004525 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07004526 {
4527 tCsrSSIDInfo *SsidInfo;
4528 int j;
4529 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
4530 /* Allocate num_ssid tCsrSSIDInfo structure */
4531 SsidInfo = scanRequest.SSIDs.SSIDList =
4532 ( tCsrSSIDInfo *)vos_mem_malloc(
4533 request->n_ssids*sizeof(tCsrSSIDInfo));
4534
4535 if(NULL == scanRequest.SSIDs.SSIDList)
4536 {
4537 hddLog(VOS_TRACE_LEVEL_ERROR,
4538 "memory alloc failed SSIDInfo buffer");
4539 return -ENOMEM;
4540 }
4541
4542 /* copy all the ssid's and their length */
4543 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
4544 {
4545 /* get the ssid length */
4546 SsidInfo->SSID.length = request->ssids[j].ssid_len;
4547 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
4548 SsidInfo->SSID.length);
4549 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
4550 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
4551 j, SsidInfo->SSID.ssId);
4552 }
4553 /* set the scan type to active */
4554 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4555 }
4556 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4557 {
4558 /* set the scan type to active */
4559 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4560 }
4561 else
4562 {
4563 /*Set the scan type to default type, in this case it is ACTIVE*/
4564 scanRequest.scanType = pScanInfo->scan_mode;
4565 }
4566 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
4567 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4568 }
4569 else
4570 {
4571 /* set the scan type to active */
4572 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4573 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4574
4575 /* set min and max channel time to zero */
4576 scanRequest.minChnTime = 0;
4577 scanRequest.maxChnTime = 0;
4578 }
4579
4580 /* set BSSType to default type */
4581 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4582
4583 /*TODO: scan the requested channels only*/
4584
4585 /*Right now scanning all the channels */
4586 if( request )
4587 {
4588 if( request->n_channels )
4589 {
4590 channelList = vos_mem_malloc( request->n_channels );
4591 if( NULL == channelList )
4592 {
4593 status = -ENOMEM;
4594 goto free_mem;
4595 }
4596
4597 for( i = 0 ; i < request->n_channels ; i++ )
4598 channelList[i] = request->channels[i]->hw_value;
4599 }
4600
4601 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4602 scanRequest.ChannelInfo.ChannelList = channelList;
4603
4604 /* set requestType to full scan */
4605 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004606
4607 /* Flush the scan results(only p2p beacons) for STA scan and P2P
4608 * search (Flush on both full scan and social scan but not on single
4609 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
4610 */
4611
4612 /* Supplicant does single channel scan after 8-way handshake
4613 * and in that case driver shoudnt flush scan results. If
4614 * driver flushes the scan results here and unfortunately if
4615 * the AP doesnt respond to our probe req then association
4616 * fails which is not desired
4617 */
4618
4619 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4620 {
4621 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4622 pAdapter->sessionId );
4623 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004624
4625 if( request->ie_len )
4626 {
4627 /* save this for future association (join requires this) */
4628 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4629 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4630 pScanInfo->scanAddIE.length = request->ie_len;
4631
4632 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004633 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4634 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004635 )
4636 {
4637 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4638 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4639 }
4640
4641 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4642 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4643
Jeff Johnson295189b2012-06-20 16:38:30 -07004644 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4645 request->ie_len);
4646 if (pP2pIe != NULL)
4647 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004648#ifdef WLAN_FEATURE_P2P_DEBUG
4649 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4650 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4651 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4652 {
4653 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4654 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4655 "Go nego completed to Connection is started");
4656 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4657 "for 8way Handshake");
4658 }
4659 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4660 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4661 {
4662 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4663 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4664 "Disconnected state to Connection is started");
4665 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4666 "for 4way Handshake");
4667 }
4668#endif
4669
Jeff Johnsone7245742012-09-05 17:12:55 -07004670 /* no_cck will be set during p2p find to disable 11b rates */
4671 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004672 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004673 hddLog(VOS_TRACE_LEVEL_INFO,
4674 "%s: This is a P2P Search", __func__);
4675 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004676
Jeff Johnsone7245742012-09-05 17:12:55 -07004677 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4678 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004679 /* set requestType to P2P Discovery */
4680 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004681 }
4682
4683 /*
4684 Skip Dfs Channel in case of P2P Search
4685 if it is set in ini file
4686 */
4687 if(cfg_param->skipDfsChnlInP2pSearch)
4688 {
4689 scanRequest.skipDfsChnlInP2pSearch = 1;
4690 }
4691 else
4692 {
4693 scanRequest.skipDfsChnlInP2pSearch = 0;
4694 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004695
Jeff Johnson295189b2012-06-20 16:38:30 -07004696 }
4697 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004698 }
4699 }
4700
4701 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4702
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004703 /* acquire the wakelock to avoid the apps suspend during the scan. To
4704 * address the following issues.
4705 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4706 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4707 * for long time, this result in apps running at full power for long time.
4708 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4709 * be stuck in full power because of resume BMPS
4710 */
4711 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004712
4713 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004714 pAdapter->sessionId, &scanRequest, &scanId,
4715 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004716
Jeff Johnson295189b2012-06-20 16:38:30 -07004717 if (eHAL_STATUS_SUCCESS != status)
4718 {
4719 hddLog(VOS_TRACE_LEVEL_ERROR,
4720 "%s: sme_ScanRequest returned error %d", __func__, status);
4721 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004722 if(eHAL_STATUS_RESOURCES == status)
4723 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004724 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 -07004725 status = -EBUSY;
4726 } else {
4727 status = -EIO;
4728 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004729 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004730 goto free_mem;
4731 }
4732
4733 pScanInfo->mScanPending = TRUE;
4734 pAdapter->request = request;
4735 pScanInfo->scanId = scanId;
4736
4737 complete(&pScanInfo->scan_req_completion_event);
4738
4739free_mem:
4740 if( scanRequest.SSIDs.SSIDList )
4741 {
4742 vos_mem_free(scanRequest.SSIDs.SSIDList);
4743 }
4744
4745 if( channelList )
4746 vos_mem_free( channelList );
4747
4748 EXIT();
4749
4750 return status;
4751}
4752
4753/*
4754 * FUNCTION: wlan_hdd_cfg80211_connect_start
4755 * This function is used to start the association process
4756 */
4757int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004758 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004759{
4760 int status = 0;
4761 hdd_wext_state_t *pWextState;
4762 v_U32_t roamId;
4763 tCsrRoamProfile *pRoamProfile;
4764 eMib_dot11DesiredBssType connectedBssType;
4765 eCsrAuthType RSNAuthType;
4766
4767 ENTER();
4768
4769 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4770
4771 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4772 {
4773 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4774 return -EINVAL;
4775 }
4776
4777 pRoamProfile = &pWextState->roamProfile;
4778
4779 if (pRoamProfile)
4780 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004781 int ret = 0;
4782 hdd_station_ctx_t *pHddStaCtx;
4783 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4784 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4785
4786 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4787 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4788 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004789 {
4790 /* Issue disconnect to CSR */
4791 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4792 if( eHAL_STATUS_SUCCESS ==
4793 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4794 pAdapter->sessionId,
4795 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4796 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004797 ret = wait_for_completion_interruptible_timeout(
4798 &pAdapter->disconnect_comp_var,
4799 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4800 if (0 == ret)
4801 {
4802 VOS_ASSERT(0);
4803 }
4804 }
4805 }
4806 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4807 {
4808 ret = wait_for_completion_interruptible_timeout(
4809 &pAdapter->disconnect_comp_var,
4810 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4811 if (0 == ret)
4812 {
4813 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004814 }
4815 }
4816
4817 if (HDD_WMM_USER_MODE_NO_QOS ==
4818 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4819 {
4820 /*QoS not enabled in cfg file*/
4821 pRoamProfile->uapsd_mask = 0;
4822 }
4823 else
4824 {
4825 /*QoS enabled, update uapsd mask from cfg file*/
4826 pRoamProfile->uapsd_mask =
4827 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4828 }
4829
4830 pRoamProfile->SSIDs.numOfSSIDs = 1;
4831 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4832 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
4833 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
4834 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4835 ssid, ssid_len);
4836
4837 if (bssid)
4838 {
4839 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4840 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4841 WNI_CFG_BSSID_LEN);
4842 /* Save BSSID in seperate variable as well, as RoamProfile
4843 BSSID is getting zeroed out in the association process. And in
4844 case of join failure we should send valid BSSID to supplicant
4845 */
4846 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4847 WNI_CFG_BSSID_LEN);
4848 }
4849
4850 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4851 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4852 {
4853 /*set gen ie*/
4854 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4855 /*set auth*/
4856 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4857 }
4858 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4859 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4860 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4861 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4862 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4863 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4864 )
4865 {
4866 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4867 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4868 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4869 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4870 eCSR_AUTH_TYPE_AUTOSWITCH;
4871 pWextState->roamProfile.AuthType.authType[0] =
4872 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4873 }
4874#ifdef FEATURE_WLAN_WAPI
4875 if (pAdapter->wapi_info.nWapiMode)
4876 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004877 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004878 switch (pAdapter->wapi_info.wapiAuthMode)
4879 {
4880 case WAPI_AUTH_MODE_PSK:
4881 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004882 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004883 pAdapter->wapi_info.wapiAuthMode);
4884 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4885 break;
4886 }
4887 case WAPI_AUTH_MODE_CERT:
4888 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004889 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004890 pAdapter->wapi_info.wapiAuthMode);
4891 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4892 break;
4893 }
4894 } // End of switch
4895 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4896 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4897 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004898 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004899 pRoamProfile->AuthType.numEntries = 1;
4900 pRoamProfile->EncryptionType.numEntries = 1;
4901 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4902 pRoamProfile->mcEncryptionType.numEntries = 1;
4903 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4904 }
4905 }
4906#endif /* FEATURE_WLAN_WAPI */
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05304907#ifdef WLAN_FEATURE_GTK_OFFLOAD
4908 /* Initializing gtkOffloadRequestParams */
4909 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4910 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4911 {
4912 pHddStaCtx->gtkOffloadRequestParams.requested = FALSE;
4913 memset(&pHddStaCtx->gtkOffloadRequestParams.gtkOffloadReqParams,
4914 0, sizeof (tSirGtkOffloadParams));
4915 }
4916#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004917 pRoamProfile->csrPersona = pAdapter->device_mode;
4918
Jeff Johnson32d95a32012-09-10 13:15:23 -07004919 if( operatingChannel )
4920 {
4921 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4922 pRoamProfile->ChannelInfo.numOfChannels = 1;
4923 }
Chet Lanctot186b5732013-03-18 10:26:30 -07004924 else
4925 {
4926 pRoamProfile->ChannelInfo.ChannelList = NULL;
4927 pRoamProfile->ChannelInfo.numOfChannels = 0;
4928 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004929
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004930 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
4931 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
4932 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
4933 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004934 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
4935 */
4936 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4937 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
4938 eConnectionState_Connecting);
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004939
Jeff Johnson295189b2012-06-20 16:38:30 -07004940 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4941 pAdapter->sessionId, pRoamProfile, &roamId);
4942
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004943 if( (eHAL_STATUS_SUCCESS != status) &&
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304944 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
4945
4946 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004947 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
4948 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
4949 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304950 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004951 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304952 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004953
4954 pRoamProfile->ChannelInfo.ChannelList = NULL;
4955 pRoamProfile->ChannelInfo.numOfChannels = 0;
4956
Jeff Johnson295189b2012-06-20 16:38:30 -07004957 }
4958 else
4959 {
4960 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4961 return -EINVAL;
4962 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004963 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004964 return status;
4965}
4966
4967/*
4968 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4969 * This function is used to set the authentication type (OPEN/SHARED).
4970 *
4971 */
4972static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4973 enum nl80211_auth_type auth_type)
4974{
4975 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4976 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4977
4978 ENTER();
4979
4980 /*set authentication type*/
4981 switch (auth_type)
4982 {
4983 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4984 case NL80211_AUTHTYPE_AUTOMATIC:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07004985#ifdef WLAN_FEATURE_VOWIFI_11R
4986 case NL80211_AUTHTYPE_FT:
4987#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07004988 hddLog(VOS_TRACE_LEVEL_INFO,
4989 "%s: set authentication type to OPEN", __func__);
4990 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4991 break;
4992
4993 case NL80211_AUTHTYPE_SHARED_KEY:
4994 hddLog(VOS_TRACE_LEVEL_INFO,
4995 "%s: set authentication type to SHARED", __func__);
4996 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4997 break;
4998#ifdef FEATURE_WLAN_CCX
4999 case NL80211_AUTHTYPE_NETWORK_EAP:
5000 hddLog(VOS_TRACE_LEVEL_INFO,
5001 "%s: set authentication type to CCKM WPA", __func__);
5002 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
5003 break;
5004#endif
5005
5006
5007 default:
5008 hddLog(VOS_TRACE_LEVEL_ERROR,
5009 "%s: Unsupported authentication type %d", __func__,
5010 auth_type);
5011 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
5012 return -EINVAL;
5013 }
5014
5015 pWextState->roamProfile.AuthType.authType[0] =
5016 pHddStaCtx->conn_info.authType;
5017 return 0;
5018}
5019
5020/*
5021 * FUNCTION: wlan_hdd_set_akm_suite
5022 * This function is used to set the key mgmt type(PSK/8021x).
5023 *
5024 */
5025static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
5026 u32 key_mgmt
5027 )
5028{
5029 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5030 ENTER();
5031
5032 /*set key mgmt type*/
5033 switch(key_mgmt)
5034 {
5035 case WLAN_AKM_SUITE_PSK:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05305036#ifdef WLAN_FEATURE_VOWIFI_11R
5037 case WLAN_AKM_SUITE_FT_PSK:
5038#endif
5039 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
Jeff Johnson295189b2012-06-20 16:38:30 -07005040 __func__);
5041 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
5042 break;
5043
5044 case WLAN_AKM_SUITE_8021X:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05305045#ifdef WLAN_FEATURE_VOWIFI_11R
5046 case WLAN_AKM_SUITE_FT_8021X:
5047#endif
5048 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
Jeff Johnson295189b2012-06-20 16:38:30 -07005049 __func__);
5050 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
5051 break;
5052#ifdef FEATURE_WLAN_CCX
5053#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
5054#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
5055 case WLAN_AKM_SUITE_CCKM:
5056 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
5057 __func__);
5058 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
5059 break;
5060#endif
5061
5062 default:
5063 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
5064 __func__, key_mgmt);
5065 return -EINVAL;
5066
5067 }
5068 return 0;
5069}
5070
5071/*
5072 * FUNCTION: wlan_hdd_cfg80211_set_cipher
5073 * This function is used to set the encryption type
5074 * (NONE/WEP40/WEP104/TKIP/CCMP).
5075 */
5076static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
5077 u32 cipher,
5078 bool ucast
5079 )
5080{
5081 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5082 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5083 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5084
5085 ENTER();
5086
5087 if (!cipher)
5088 {
5089 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
5090 __func__, cipher);
5091 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5092 }
5093 else
5094 {
5095
5096 /*set encryption method*/
5097 switch (cipher)
5098 {
5099 case IW_AUTH_CIPHER_NONE:
5100 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5101 break;
5102
5103 case WLAN_CIPHER_SUITE_WEP40:
5104 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
5105 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
5106 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
5107 else
5108 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5109 break;
5110
5111 case WLAN_CIPHER_SUITE_WEP104:
5112 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
5113 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
5114 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
5115 else
5116 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
5117 break;
5118
5119 case WLAN_CIPHER_SUITE_TKIP:
5120 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5121 break;
5122
5123 case WLAN_CIPHER_SUITE_CCMP:
5124 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5125 break;
5126#ifdef FEATURE_WLAN_WAPI
5127 case WLAN_CIPHER_SUITE_SMS4:
5128 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
5129 break;
5130#endif
5131
5132#ifdef FEATURE_WLAN_CCX
5133 case WLAN_CIPHER_SUITE_KRK:
5134 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
5135 break;
5136#endif
5137 default:
5138 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
5139 __func__, cipher);
5140 return -EOPNOTSUPP;
5141 }
5142 }
5143
5144 if (ucast)
5145 {
5146 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
5147 __func__, encryptionType);
5148 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5149 pWextState->roamProfile.EncryptionType.numEntries = 1;
5150 pWextState->roamProfile.EncryptionType.encryptionType[0] =
5151 encryptionType;
5152 }
5153 else
5154 {
5155 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
5156 __func__, encryptionType);
5157 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
5158 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
5159 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
5160 }
5161
5162 return 0;
5163}
5164
5165
5166/*
5167 * FUNCTION: wlan_hdd_cfg80211_set_ie
5168 * This function is used to parse WPA/RSN IE's.
5169 */
5170int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
5171 u8 *ie,
5172 size_t ie_len
5173 )
5174{
5175 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5176 u8 *genie = ie;
5177 v_U16_t remLen = ie_len;
5178#ifdef FEATURE_WLAN_WAPI
5179 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
5180 u16 *tmp;
5181 v_U16_t akmsuiteCount;
5182 int *akmlist;
5183#endif
5184 ENTER();
5185
5186 /* clear previous assocAddIE */
5187 pWextState->assocAddIE.length = 0;
5188 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
5189
5190 while (remLen >= 2)
5191 {
5192 v_U16_t eLen = 0;
5193 v_U8_t elementId;
5194 elementId = *genie++;
5195 eLen = *genie++;
5196 remLen -= 2;
5197
5198 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
5199 __func__, elementId, eLen);
5200
5201 switch ( elementId )
5202 {
5203 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005204 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 -07005205 {
5206 hddLog(VOS_TRACE_LEVEL_ERROR,
5207 "%s: Invalid WPA IE", __func__);
5208 return -EINVAL;
5209 }
5210 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
5211 {
5212 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5213 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
5214 __func__, eLen + 2);
5215
5216 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5217 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005218 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
5219 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005220 VOS_ASSERT(0);
5221 return -ENOMEM;
5222 }
5223 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5224 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5225 pWextState->assocAddIE.length += eLen + 2;
5226
5227 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
5228 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5229 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5230 }
5231 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
5232 {
5233 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
5234 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5235 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
5236 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
5237 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
5238 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005239 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
5240 P2P_OUI_TYPE_SIZE))
5241 /*Consider P2P IE, only for P2P Client */
5242 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5243 {
5244 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5245 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
5246 __func__, eLen + 2);
5247
5248 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5249 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005250 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5251 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005252 VOS_ASSERT(0);
5253 return -ENOMEM;
5254 }
5255 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5256 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5257 pWextState->assocAddIE.length += eLen + 2;
5258
5259 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5260 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5261 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005262#ifdef WLAN_FEATURE_WFD
5263 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
5264 WFD_OUI_TYPE_SIZE))
5265 /*Consider WFD IE, only for P2P Client */
5266 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5267 {
5268 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5269 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
5270 __func__, eLen + 2);
5271
5272 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5273 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005274 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5275 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005276 VOS_ASSERT(0);
5277 return -ENOMEM;
5278 }
5279 // WFD IE is saved to Additional IE ; it should be accumulated to handle
5280 // WPS IE + P2P IE + WFD IE
5281 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5282 pWextState->assocAddIE.length += eLen + 2;
5283
5284 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5285 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5286 }
5287#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005288 /* Appending HS 2.0 Indication Element in Assiciation Request */
5289 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005290 HS20_OUI_TYPE_SIZE)) )
5291 {
5292 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5293 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
5294 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005295
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005296 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5297 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005298 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5299 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005300 VOS_ASSERT(0);
5301 return -ENOMEM;
5302 }
5303 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5304 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005305
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005306 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5307 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5308 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005309
Jeff Johnson295189b2012-06-20 16:38:30 -07005310 break;
5311 case DOT11F_EID_RSN:
5312 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
5313 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5314 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
5315 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
5316 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
5317 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005318 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
5319 case DOT11F_EID_EXTCAP:
5320 {
5321 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5322 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
5323 __func__, eLen + 2);
5324
5325 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5326 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005327 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5328 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005329 VOS_ASSERT(0);
5330 return -ENOMEM;
5331 }
5332 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5333 pWextState->assocAddIE.length += eLen + 2;
5334
5335 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5336 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5337 break;
5338 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005339#ifdef FEATURE_WLAN_WAPI
5340 case WLAN_EID_WAPI:
5341 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
5342 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
5343 pAdapter->wapi_info.nWapiMode);
5344 tmp = (u16 *)ie;
5345 tmp = tmp + 2; // Skip element Id and Len, Version
5346 akmsuiteCount = WPA_GET_LE16(tmp);
5347 tmp = tmp + 1;
5348 akmlist = (int *)(tmp);
5349 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
5350 {
5351 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
5352 }
5353 else
5354 {
5355 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
5356 VOS_ASSERT(0);
5357 return -EINVAL;
5358 }
5359
5360 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
5361 {
5362 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005363 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005364 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
5365 }
5366 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
5367 {
5368 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005369 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005370 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
5371 }
5372 break;
5373#endif
5374 default:
5375 hddLog (VOS_TRACE_LEVEL_ERROR,
5376 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005377 /* when Unknown IE is received we should break and continue
5378 * to the next IE in the buffer instead we were returning
5379 * so changing this to break */
5380 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005381 }
5382 genie += eLen;
5383 remLen -= eLen;
5384 }
5385 EXIT();
5386 return 0;
5387}
5388
5389/*
5390 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5391 * This function is used to initialize the security
5392 * parameters during connect operation.
5393 */
5394int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
5395 struct cfg80211_connect_params *req
5396 )
5397{
5398 int status = 0;
5399 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5400 ENTER();
5401
5402 /*set wpa version*/
5403 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5404
5405 if (req->crypto.wpa_versions)
5406 {
5407 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
5408 && ( (req->ie_len)
5409 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
5410 // Make sure that it is including a WPA IE.
5411 /* Currently NL is putting WPA version 1 even for open,
5412 * since p2p ie is also put in same buffer.
5413 * */
5414 {
5415 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5416 }
5417 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
5418 {
5419 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5420 }
5421 }
5422
5423 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
5424 pWextState->wpaVersion);
5425
5426 /*set authentication type*/
5427 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
5428
5429 if (0 > status)
5430 {
5431 hddLog(VOS_TRACE_LEVEL_ERROR,
5432 "%s: failed to set authentication type ", __func__);
5433 return status;
5434 }
5435
5436 /*set key mgmt type*/
5437 if (req->crypto.n_akm_suites)
5438 {
5439 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
5440 if (0 > status)
5441 {
5442 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
5443 __func__);
5444 return status;
5445 }
5446 }
5447
5448 /*set pairwise cipher type*/
5449 if (req->crypto.n_ciphers_pairwise)
5450 {
5451 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
5452 req->crypto.ciphers_pairwise[0], true);
5453 if (0 > status)
5454 {
5455 hddLog(VOS_TRACE_LEVEL_ERROR,
5456 "%s: failed to set unicast cipher type", __func__);
5457 return status;
5458 }
5459 }
5460 else
5461 {
5462 /*Reset previous cipher suite to none*/
5463 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
5464 if (0 > status)
5465 {
5466 hddLog(VOS_TRACE_LEVEL_ERROR,
5467 "%s: failed to set unicast cipher type", __func__);
5468 return status;
5469 }
5470 }
5471
5472 /*set group cipher type*/
5473 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
5474 false);
5475
5476 if (0 > status)
5477 {
5478 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
5479 __func__);
5480 return status;
5481 }
5482
Chet Lanctot186b5732013-03-18 10:26:30 -07005483#ifdef WLAN_FEATURE_11W
5484 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
5485#endif
5486
Jeff Johnson295189b2012-06-20 16:38:30 -07005487 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
5488 if (req->ie_len)
5489 {
5490 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
5491 if ( 0 > status)
5492 {
5493 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
5494 __func__);
5495 return status;
5496 }
5497 }
5498
5499 /*incase of WEP set default key information*/
5500 if (req->key && req->key_len)
5501 {
5502 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
5503 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
5504 )
5505 {
5506 if ( IW_AUTH_KEY_MGMT_802_1X
5507 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
5508 {
5509 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
5510 __func__);
5511 return -EOPNOTSUPP;
5512 }
5513 else
5514 {
5515 u8 key_len = req->key_len;
5516 u8 key_idx = req->key_idx;
5517
5518 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
5519 && (CSR_MAX_NUM_KEY > key_idx)
5520 )
5521 {
5522 hddLog(VOS_TRACE_LEVEL_INFO,
5523 "%s: setting default wep key, key_idx = %hu key_len %hu",
5524 __func__, key_idx, key_len);
5525 vos_mem_copy(
5526 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
5527 req->key, key_len);
5528 pWextState->roamProfile.Keys.KeyLength[key_idx] =
5529 (u8)key_len;
5530 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
5531 }
5532 }
5533 }
5534 }
5535
5536 return status;
5537}
5538
5539/*
5540 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5541 * This function is used to initialize the security
5542 * parameters during connect operation.
5543 */
5544static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
5545 struct net_device *ndev,
5546 struct cfg80211_connect_params *req
5547 )
5548{
5549 int status = 0;
5550 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
5551 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
5552 hdd_context_t *pHddCtx = NULL;
5553
5554 ENTER();
5555
5556 hddLog(VOS_TRACE_LEVEL_INFO,
5557 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5558
5559 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5560 {
5561 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5562 "%s:LOGP in Progress. Ignore!!!", __func__);
5563 return -EAGAIN;
5564 }
5565
5566#ifdef WLAN_BTAMP_FEATURE
5567 //Infra connect not supported when AMP traffic is on.
5568 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
5569 {
5570 hddLog(VOS_TRACE_LEVEL_ERROR,
5571 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005572 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07005573 }
5574#endif
5575 /*initialise security parameters*/
5576 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
5577
5578 if ( 0 > status)
5579 {
5580 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
5581 __func__);
5582 return status;
5583 }
5584
5585 //If Device Mode is Station Concurrent Sessions Exit BMps
Jeff Johnsona8a1a482012-12-12 16:49:33 -08005586 //P2P Mode will be taken care in Open/close adapter
Jeff Johnson295189b2012-06-20 16:38:30 -07005587 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
5588 (vos_concurrent_sessions_running()))
5589 {
5590 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5591
5592 if (NULL != pVosContext)
5593 {
5594 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5595 if(NULL != pHddCtx)
5596 {
5597 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
5598 }
5599 }
5600 }
5601
Mohit Khanna765234a2012-09-11 15:08:35 -07005602 if ( req->channel )
5603 {
5604 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5605 req->ssid_len, req->bssid,
5606 req->channel->hw_value);
5607 }
5608 else
5609 {
5610 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5611 req->ssid_len, req->bssid,
5612 0);
5613 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005614
5615 if (0 > status)
5616 {
5617 //ReEnable BMPS if disabled
5618 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5619 (NULL != pHddCtx))
5620 {
5621 //ReEnable Bmps and Imps back
5622 hdd_enable_bmps_imps(pHddCtx);
5623 }
5624
5625 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5626 return status;
5627 }
5628 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
5629 EXIT();
5630 return status;
5631}
5632
5633
5634/*
5635 * FUNCTION: wlan_hdd_cfg80211_disconnect
5636 * This function is used to issue a disconnect request to SME
5637 */
5638static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
5639 struct net_device *dev,
5640 u16 reason
5641 )
5642{
5643 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5644 tCsrRoamProfile *pRoamProfile =
5645 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
5646 int status = 0;
5647 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005648#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005649 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005650 tANI_U8 staIdx;
5651#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005652
5653 ENTER();
5654
5655 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
5656 __func__,pAdapter->device_mode);
5657
5658 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5659 __func__, reason);
5660
5661 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
5662 {
5663 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5664 "%s:LOGP in Progress. Ignore!!!",__func__);
5665 return -EAGAIN;
5666 }
5667 if (NULL != pRoamProfile)
5668 {
5669 /*issue disconnect request to SME, if station is in connected state*/
5670 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
5671 {
5672 eCsrRoamDisconnectReason reasonCode =
5673 eCSR_DISCONNECT_REASON_UNSPECIFIED;
5674 switch(reason)
5675 {
5676 case WLAN_REASON_MIC_FAILURE:
5677 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
5678 break;
5679
5680 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
5681 case WLAN_REASON_DISASSOC_AP_BUSY:
5682 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
5683 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
5684 break;
5685
5686 case WLAN_REASON_PREV_AUTH_NOT_VALID:
5687 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
5688 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
5689 break;
5690
5691 case WLAN_REASON_DEAUTH_LEAVING:
5692 default:
5693 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
5694 break;
5695 }
5696 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5697 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
5698 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5699
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005700#ifdef FEATURE_WLAN_TDLS
5701 /* First clean up the tdls peers if any */
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005702 for (staIdx = 0 ; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005703 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005704 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId == pAdapter->sessionId) &&
5705 (pHddCtx->tdlsConnInfo[staIdx].staId))
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005706 {
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005707 uint8 *mac;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005708 mac = pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005709 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07005710 "%s: call sme_DeleteTdlsPeerSta staId %d sessionId %d " MAC_ADDRESS_STR,
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005711 __func__, pHddCtx->tdlsConnInfo[staIdx].staId, pAdapter->sessionId,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07005712 MAC_ADDR_ARRAY(mac));
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005713 sme_DeleteTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005714 pAdapter->sessionId,
5715 mac);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005716 }
5717 }
5718#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005719 /*issue disconnect*/
5720 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5721 pAdapter->sessionId, reasonCode);
5722
5723 if ( 0 != status)
5724 {
5725 hddLog(VOS_TRACE_LEVEL_ERROR,
5726 "%s csrRoamDisconnect failure, returned %d \n",
5727 __func__, (int)status );
5728 return -EINVAL;
5729 }
5730
5731 wait_for_completion_interruptible_timeout(
5732 &pAdapter->disconnect_comp_var,
5733 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5734
5735
5736 /*stop tx queues*/
5737 netif_tx_disable(dev);
5738 netif_carrier_off(dev);
5739 }
5740 }
5741 else
5742 {
5743 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
5744 }
5745
5746 return status;
5747}
5748
5749/*
5750 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
5751 * This function is used to initialize the security
5752 * settings in IBSS mode.
5753 */
5754static int wlan_hdd_cfg80211_set_privacy_ibss(
5755 hdd_adapter_t *pAdapter,
5756 struct cfg80211_ibss_params *params
5757 )
5758{
5759 int status = 0;
5760 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5761 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5762 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5763
5764 ENTER();
5765
5766 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5767
5768 if (params->ie_len && ( NULL != params->ie) )
5769 {
5770 if (WLAN_EID_RSN == params->ie[0])
5771 {
5772 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5773 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5774 }
5775 else
5776 {
5777 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5778 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5779 }
5780 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
5781
5782 if (0 > status)
5783 {
5784 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
5785 __func__);
5786 return status;
5787 }
5788 }
5789
5790 pWextState->roamProfile.AuthType.authType[0] =
5791 pHddStaCtx->conn_info.authType =
5792 eCSR_AUTH_TYPE_OPEN_SYSTEM;
5793
5794 if (params->privacy)
5795 {
5796 /* Security enabled IBSS, At this time there is no information available
5797 * about the security paramters, so initialise the encryption type to
5798 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
5799 * The correct security parameters will be updated later in
5800 * wlan_hdd_cfg80211_add_key */
5801 /* Hal expects encryption type to be set inorder
5802 *enable privacy bit in beacons */
5803
5804 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5805 }
5806
5807 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5808 pWextState->roamProfile.EncryptionType.numEntries = 1;
5809 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
5810
5811 return status;
5812}
5813
5814/*
5815 * FUNCTION: wlan_hdd_cfg80211_join_ibss
5816 * This function is used to create/join an IBSS
5817 */
5818static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
5819 struct net_device *dev,
5820 struct cfg80211_ibss_params *params
5821 )
5822{
5823 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5824 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5825 tCsrRoamProfile *pRoamProfile;
5826 int status;
5827 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5828
5829 ENTER();
5830
5831 hddLog(VOS_TRACE_LEVEL_INFO,
5832 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5833
5834 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5835 {
5836 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5837 "%s:LOGP in Progress. Ignore!!!", __func__);
5838 return -EAGAIN;
5839 }
5840
5841 if (NULL == pWextState)
5842 {
5843 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5844 __func__);
5845 return -EIO;
5846 }
5847
5848 pRoamProfile = &pWextState->roamProfile;
5849
5850 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
5851 {
5852 hddLog (VOS_TRACE_LEVEL_ERROR,
5853 "%s Interface type is not set to IBSS \n", __func__);
5854 return -EINVAL;
5855 }
5856
5857 /* Set Channel */
5858 if (NULL != params->channel)
5859 {
5860 u8 channelNum;
5861 if (IEEE80211_BAND_5GHZ == params->channel->band)
5862 {
5863 hddLog(VOS_TRACE_LEVEL_ERROR,
5864 "%s: IBSS join is called with unsupported band %d",
5865 __func__, params->channel->band);
5866 return -EOPNOTSUPP;
5867 }
5868
5869 /* Get channel number */
5870 channelNum =
5871 ieee80211_frequency_to_channel(params->channel->center_freq);
5872
5873 /*TODO: use macro*/
5874 if (14 >= channelNum)
5875 {
5876 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5877 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5878 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5879 int indx;
5880
5881 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5882 validChan, &numChans))
5883 {
5884 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
5885 __func__);
5886 return -EOPNOTSUPP;
5887 }
5888
5889 for (indx = 0; indx < numChans; indx++)
5890 {
5891 if (channelNum == validChan[indx])
5892 {
5893 break;
5894 }
5895 }
5896 if (indx >= numChans)
5897 {
5898 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
5899 __func__, channelNum);
5900 return -EINVAL;
5901 }
5902 /* Set the Operational Channel */
5903 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
5904 channelNum);
5905 pRoamProfile->ChannelInfo.numOfChannels = 1;
5906 pHddStaCtx->conn_info.operationChannel = channelNum;
5907 pRoamProfile->ChannelInfo.ChannelList =
5908 &pHddStaCtx->conn_info.operationChannel;
5909 }
5910 else
5911 {
5912 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5913 __func__, channelNum);
5914 return -EINVAL;
5915 }
5916 }
5917
5918 /* Initialize security parameters */
5919 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5920 if (status < 0)
5921 {
5922 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5923 __func__);
5924 return status;
5925 }
5926
5927 /* Issue connect start */
5928 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005929 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005930
5931 if (0 > status)
5932 {
5933 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5934 return status;
5935 }
5936
5937 return 0;
5938}
5939
5940/*
5941 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5942 * This function is used to leave an IBSS
5943 */
5944static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5945 struct net_device *dev
5946 )
5947{
5948 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5949 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5950 tCsrRoamProfile *pRoamProfile;
5951
5952 ENTER();
5953
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005954 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5955 {
5956 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5957 "%s:LOGP in Progress. Ignore!!!", __func__);
5958 return -EAGAIN;
5959 }
5960
Jeff Johnson295189b2012-06-20 16:38:30 -07005961 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5962 if (NULL == pWextState)
5963 {
5964 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5965 __func__);
5966 return -EIO;
5967 }
5968
5969 pRoamProfile = &pWextState->roamProfile;
5970
5971 /* Issue disconnect only if interface type is set to IBSS */
5972 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5973 {
5974 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5975 __func__);
5976 return -EINVAL;
5977 }
5978
5979 /* Issue Disconnect request */
5980 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5981 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5982 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5983
5984 return 0;
5985}
5986
5987/*
5988 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5989 * This function is used to set the phy parameters
5990 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5991 */
5992static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5993 u32 changed)
5994{
5995 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5996 tHalHandle hHal = pHddCtx->hHal;
5997
5998 ENTER();
5999
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006000 if ( pHddCtx->isLogpInProgress )
6001 {
6002 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6003 "%s:LOGP in Progress. Ignore!!!", __func__);
6004 return -EAGAIN;
6005 }
6006
Jeff Johnson295189b2012-06-20 16:38:30 -07006007 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
6008 {
6009 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
6010 WNI_CFG_RTS_THRESHOLD_STAMAX :
6011 wiphy->rts_threshold;
6012
6013 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
6014 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
6015 {
6016 hddLog(VOS_TRACE_LEVEL_ERROR,
6017 "%s: Invalid RTS Threshold value %hu",
6018 __func__, rts_threshold);
6019 return -EINVAL;
6020 }
6021
6022 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
6023 rts_threshold, ccmCfgSetCallback,
6024 eANI_BOOLEAN_TRUE))
6025 {
6026 hddLog(VOS_TRACE_LEVEL_ERROR,
6027 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
6028 __func__, rts_threshold);
6029 return -EIO;
6030 }
6031
6032 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
6033 rts_threshold);
6034 }
6035
6036 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
6037 {
6038 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
6039 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
6040 wiphy->frag_threshold;
6041
6042 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
6043 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
6044 {
6045 hddLog(VOS_TRACE_LEVEL_ERROR,
6046 "%s: Invalid frag_threshold value %hu", __func__,
6047 frag_threshold);
6048 return -EINVAL;
6049 }
6050
6051 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
6052 frag_threshold, ccmCfgSetCallback,
6053 eANI_BOOLEAN_TRUE))
6054 {
6055 hddLog(VOS_TRACE_LEVEL_ERROR,
6056 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
6057 __func__, frag_threshold);
6058 return -EIO;
6059 }
6060
6061 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
6062 frag_threshold);
6063 }
6064
6065 if ((changed & WIPHY_PARAM_RETRY_SHORT)
6066 || (changed & WIPHY_PARAM_RETRY_LONG))
6067 {
6068 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
6069 wiphy->retry_short :
6070 wiphy->retry_long;
6071
6072 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
6073 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
6074 {
6075 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
6076 __func__, retry_value);
6077 return -EINVAL;
6078 }
6079
6080 if (changed & WIPHY_PARAM_RETRY_SHORT)
6081 {
6082 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
6083 retry_value, ccmCfgSetCallback,
6084 eANI_BOOLEAN_TRUE))
6085 {
6086 hddLog(VOS_TRACE_LEVEL_ERROR,
6087 "%s: ccmCfgSetInt failed for long retry count %hu",
6088 __func__, retry_value);
6089 return -EIO;
6090 }
6091 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
6092 __func__, retry_value);
6093 }
6094 else if (changed & WIPHY_PARAM_RETRY_SHORT)
6095 {
6096 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
6097 retry_value, ccmCfgSetCallback,
6098 eANI_BOOLEAN_TRUE))
6099 {
6100 hddLog(VOS_TRACE_LEVEL_ERROR,
6101 "%s: ccmCfgSetInt failed for short retry count %hu",
6102 __func__, retry_value);
6103 return -EIO;
6104 }
6105 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
6106 __func__, retry_value);
6107 }
6108 }
6109
6110 return 0;
6111}
6112
6113/*
6114 * FUNCTION: wlan_hdd_cfg80211_set_txpower
6115 * This function is used to set the txpower
6116 */
6117static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
6118#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
6119 enum tx_power_setting type,
6120#else
6121 enum nl80211_tx_power_setting type,
6122#endif
6123 int dbm)
6124{
6125 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6126 tHalHandle hHal = pHddCtx->hHal;
6127 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
6128 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
6129
6130 ENTER();
6131
6132 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
6133 dbm, ccmCfgSetCallback,
6134 eANI_BOOLEAN_TRUE))
6135 {
6136 hddLog(VOS_TRACE_LEVEL_ERROR,
6137 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
6138 return -EIO;
6139 }
6140
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006141 if ( pHddCtx->isLogpInProgress )
6142 {
6143 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6144 "%s:LOGP in Progress. Ignore!!!", __func__);
6145 return -EAGAIN;
6146 }
6147
Jeff Johnson295189b2012-06-20 16:38:30 -07006148 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
6149 dbm);
6150
6151 switch(type)
6152 {
6153 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
6154 /* Fall through */
6155 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
6156 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
6157 {
6158 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
6159 __func__);
6160 return -EIO;
6161 }
6162 break;
6163 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
6164 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
6165 __func__);
6166 return -EOPNOTSUPP;
6167 break;
6168 default:
6169 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
6170 __func__, type);
6171 return -EIO;
6172 }
6173
6174 return 0;
6175}
6176
6177/*
6178 * FUNCTION: wlan_hdd_cfg80211_get_txpower
6179 * This function is used to read the txpower
6180 */
6181static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
6182{
6183
6184 hdd_adapter_t *pAdapter;
6185 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6186
Jeff Johnsone7245742012-09-05 17:12:55 -07006187 ENTER();
6188
Jeff Johnson295189b2012-06-20 16:38:30 -07006189 if (NULL == pHddCtx)
6190 {
6191 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
6192 *dbm = 0;
6193 return -ENOENT;
6194 }
6195
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006196 if ( pHddCtx->isLogpInProgress )
6197 {
6198 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6199 "%s:LOGP in Progress. Ignore!!!", __func__);
6200 return -EAGAIN;
6201 }
6202
Jeff Johnson295189b2012-06-20 16:38:30 -07006203 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
6204 if (NULL == pAdapter)
6205 {
6206 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
6207 return -ENOENT;
6208 }
6209
6210 wlan_hdd_get_classAstats(pAdapter);
6211 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
6212
Jeff Johnsone7245742012-09-05 17:12:55 -07006213 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006214 return 0;
6215}
6216
6217static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
6218 u8* mac, struct station_info *sinfo)
6219{
6220 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
6221 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6222 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
6223 tANI_U8 rate_flags;
6224
6225 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6226 hdd_config_t *pCfg = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07006227
6228 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
6229 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
6230 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
6231 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
6232 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
6233 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
6234 tANI_U16 maxRate = 0;
6235 tANI_U16 myRate;
6236 tANI_U16 currentRate = 0;
6237 tANI_U8 maxSpeedMCS = 0;
6238 tANI_U8 maxMCSIdx = 0;
6239 tANI_U8 rateFlag = 1;
6240 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006241 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07006242
Leo Chang6f8870f2013-03-26 18:11:36 -07006243#ifdef WLAN_FEATURE_11AC
6244 tANI_U32 vht_mcs_map;
6245 eDataRate11ACMaxMcs vhtMaxMcs;
6246#endif /* WLAN_FEATURE_11AC */
6247
Jeff Johnsone7245742012-09-05 17:12:55 -07006248 ENTER();
6249
Jeff Johnson295189b2012-06-20 16:38:30 -07006250 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
6251 (0 == ssidlen))
6252 {
6253 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
6254 " Invalid ssidlen, %d", __func__, ssidlen);
6255 /*To keep GUI happy*/
6256 return 0;
6257 }
6258
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006259 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6260 {
6261 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6262 "%s:LOGP in Progress. Ignore!!!", __func__);
6263 return -EAGAIN;
6264 }
6265
Jeff Johnson295189b2012-06-20 16:38:30 -07006266 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
6267 sinfo->filled |= STATION_INFO_SIGNAL;
6268
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006269 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006270 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
6271
6272 //convert to the UI units of 100kbps
6273 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
6274
6275#ifdef LINKSPEED_DEBUG_ENABLED
Leo Chang6f8870f2013-03-26 18:11:36 -07006276 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 -07006277 sinfo->signal,
6278 pCfg->reportMaxLinkSpeed,
6279 myRate,
6280 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006281 (int) pCfg->linkSpeedRssiMid,
6282 (int) pCfg->linkSpeedRssiLow,
Leo Chang6f8870f2013-03-26 18:11:36 -07006283 (int) rate_flags,
6284 (int) pAdapter->hdd_stats.ClassA_stat.mcs_index);
Jeff Johnson295189b2012-06-20 16:38:30 -07006285#endif //LINKSPEED_DEBUG_ENABLED
6286
6287 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
6288 {
6289 // we do not want to necessarily report the current speed
6290 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
6291 {
6292 // report the max possible speed
6293 rssidx = 0;
6294 }
6295 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
6296 {
6297 // report the max possible speed with RSSI scaling
6298 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
6299 {
6300 // report the max possible speed
6301 rssidx = 0;
6302 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006303 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07006304 {
6305 // report middle speed
6306 rssidx = 1;
6307 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006308 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
6309 {
6310 // report middle speed
6311 rssidx = 2;
6312 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006313 else
6314 {
6315 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006316 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07006317 }
6318 }
6319 else
6320 {
6321 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
6322 hddLog(VOS_TRACE_LEVEL_ERROR,
6323 "%s: Invalid value for reportMaxLinkSpeed: %u",
6324 __func__, pCfg->reportMaxLinkSpeed);
6325 rssidx = 0;
6326 }
6327
6328 maxRate = 0;
6329
6330 /* Get Basic Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306331 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_OPERATIONAL_RATE_SET,
6332 OperationalRates, &ORLeng))
6333 {
6334 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6335 /*To keep GUI happy*/
6336 return 0;
6337 }
6338
Jeff Johnson295189b2012-06-20 16:38:30 -07006339 for (i = 0; i < ORLeng; i++)
6340 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006341 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006342 {
6343 /* Validate Rate Set */
6344 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
6345 {
6346 currentRate = supported_data_rate[j].supported_rate[rssidx];
6347 break;
6348 }
6349 }
6350 /* Update MAX rate */
6351 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6352 }
6353
6354 /* Get Extended Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306355 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
6356 ExtendedRates, &ERLeng))
6357 {
6358 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6359 /*To keep GUI happy*/
6360 return 0;
6361 }
6362
Jeff Johnson295189b2012-06-20 16:38:30 -07006363 for (i = 0; i < ERLeng; i++)
6364 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006365 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006366 {
6367 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
6368 {
6369 currentRate = supported_data_rate[j].supported_rate[rssidx];
6370 break;
6371 }
6372 }
6373 /* Update MAX rate */
6374 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6375 }
6376
6377 /* Get MCS Rate Set -- but only if we are connected at MCS
6378 rates or if we are always reporting max speed or if we have
6379 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006380 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07006381 {
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306382 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_CURRENT_MCS_SET,
6383 MCSRates, &MCSLeng))
6384 {
6385 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6386 /*To keep GUI happy*/
6387 return 0;
6388 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006389 rateFlag = 0;
Leo Chang6f8870f2013-03-26 18:11:36 -07006390#ifdef WLAN_FEATURE_11AC
6391 /* VHT80 rate has seperate rate table */
6392 if (rate_flags & eHAL_TX_RATE_VHT80)
Jeff Johnson295189b2012-06-20 16:38:30 -07006393 {
Leo Chang6f8870f2013-03-26 18:11:36 -07006394 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_rate[rateFlag];
6395 ccmCfgGetInt(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_VHT_TX_MCS_MAP, &vht_mcs_map);
6396 if (rate_flags & eHAL_TX_RATE_SGI)
Jeff Johnson295189b2012-06-20 16:38:30 -07006397 {
Leo Chang6f8870f2013-03-26 18:11:36 -07006398 rateFlag |= 1;
Jeff Johnson295189b2012-06-20 16:38:30 -07006399 }
Leo Chang6f8870f2013-03-26 18:11:36 -07006400 vhtMaxMcs = (eDataRate11ACMaxMcs)(vht_mcs_map & DATA_RATE_11AC_MCS_MASK);
6401 if (DATA_RATE_11AC_MAX_MCS_7 == vhtMaxMcs)
Jeff Johnson295189b2012-06-20 16:38:30 -07006402 {
Leo Chang6f8870f2013-03-26 18:11:36 -07006403 maxMCSIdx = 7;
6404 }
6405 else if (DATA_RATE_11AC_MAX_MCS_8 == vhtMaxMcs)
6406 {
6407 maxMCSIdx = 8;
6408 }
6409 else if (DATA_RATE_11AC_MAX_MCS_9 == vhtMaxMcs)
6410 {
6411 maxMCSIdx = 9;
6412 }
6413 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_rate[rateFlag];
6414 maxSpeedMCS = 1;
6415 if (currentRate > maxRate)
6416 {
6417 maxRate = currentRate;
6418 }
6419 }
6420 else
6421#endif /* WLAN_FEATURE_11AC */
6422 {
6423 if (rate_flags & eHAL_TX_RATE_HT40)
6424 {
6425 rateFlag |= 1;
6426 }
6427 if (rate_flags & eHAL_TX_RATE_SGI)
6428 {
6429 rateFlag |= 2;
6430 }
6431
6432 for (i = 0; i < MCSLeng; i++)
6433 {
6434 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
6435 for (j = 0; j < temp; j++)
6436 {
6437 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
6438 {
6439 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
6440 break;
6441 }
6442 }
6443 if ((j < temp) && (currentRate > maxRate))
6444 {
6445 maxRate = currentRate;
6446 maxSpeedMCS = 1;
6447 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
6448 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006449 }
6450 }
6451 }
6452
6453 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006454 if (((maxRate < myRate) && (0 == rssidx)) ||
6455 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006456 {
6457 maxRate = myRate;
6458 if (rate_flags & eHAL_TX_RATE_LEGACY)
6459 {
6460 maxSpeedMCS = 0;
6461 }
6462 else
6463 {
6464 maxSpeedMCS = 1;
6465 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6466 }
6467 }
6468
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006469 if ((!maxSpeedMCS) || (0 != rssidx))
Jeff Johnson295189b2012-06-20 16:38:30 -07006470 {
6471 sinfo->txrate.legacy = maxRate;
6472#ifdef LINKSPEED_DEBUG_ENABLED
6473 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
6474#endif //LINKSPEED_DEBUG_ENABLED
6475 }
6476 else
6477 {
6478 sinfo->txrate.mcs = maxMCSIdx;
Leo Chang6f8870f2013-03-26 18:11:36 -07006479#ifdef WLAN_FEATURE_11AC
6480 sinfo->txrate.nss = 1;
6481 if (rate_flags & eHAL_TX_RATE_VHT80)
6482 {
6483 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
6484 }
6485 else
6486#endif /* WLAN_FEATURE_11AC */
6487 {
6488 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6489 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006490 if (rate_flags & eHAL_TX_RATE_SGI)
6491 {
6492 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6493 }
6494 if (rate_flags & eHAL_TX_RATE_HT40)
6495 {
6496 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6497 }
Leo Chang6f8870f2013-03-26 18:11:36 -07006498#ifdef WLAN_FEATURE_11AC
6499 else if (rate_flags & eHAL_TX_RATE_VHT80)
6500 {
6501 sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
6502 }
6503#endif /* WLAN_FEATURE_11AC */
Jeff Johnson295189b2012-06-20 16:38:30 -07006504#ifdef LINKSPEED_DEBUG_ENABLED
6505 pr_info("Reporting MCS rate %d flags %x\n",
6506 sinfo->txrate.mcs,
6507 sinfo->txrate.flags );
6508#endif //LINKSPEED_DEBUG_ENABLED
6509 }
6510 }
6511 else
6512 {
6513 // report current rate instead of max rate
6514
6515 if (rate_flags & eHAL_TX_RATE_LEGACY)
6516 {
6517 //provide to the UI in units of 100kbps
6518 sinfo->txrate.legacy = myRate;
6519#ifdef LINKSPEED_DEBUG_ENABLED
6520 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
6521#endif //LINKSPEED_DEBUG_ENABLED
6522 }
6523 else
6524 {
6525 //must be MCS
6526 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
Leo Chang6f8870f2013-03-26 18:11:36 -07006527#ifdef WLAN_FEATURE_11AC
6528 sinfo->txrate.nss = 1;
6529 if (rate_flags & eHAL_TX_RATE_VHT80)
6530 {
6531 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
6532 }
6533 else
6534#endif /* WLAN_FEATURE_11AC */
6535 {
6536 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6537 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006538 if (rate_flags & eHAL_TX_RATE_SGI)
6539 {
6540 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6541 }
6542 if (rate_flags & eHAL_TX_RATE_HT40)
6543 {
6544 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6545 }
Leo Chang6f8870f2013-03-26 18:11:36 -07006546#ifdef WLAN_FEATURE_11AC
6547 else if (rate_flags & eHAL_TX_RATE_VHT80)
6548 {
6549 sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
6550 }
6551#endif /* WLAN_FEATURE_11AC */
Jeff Johnson295189b2012-06-20 16:38:30 -07006552#ifdef LINKSPEED_DEBUG_ENABLED
6553 pr_info("Reporting actual MCS rate %d flags %x\n",
6554 sinfo->txrate.mcs,
6555 sinfo->txrate.flags );
6556#endif //LINKSPEED_DEBUG_ENABLED
6557 }
6558 }
6559 sinfo->filled |= STATION_INFO_TX_BITRATE;
6560
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006561 sinfo->tx_packets =
6562 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
6563 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
6564 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
6565 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
6566
6567 sinfo->tx_retries =
6568 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
6569 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
6570 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
6571 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
6572
6573 sinfo->tx_failed =
6574 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
6575 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
6576 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
6577 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
6578
6579 sinfo->filled |=
6580 STATION_INFO_TX_PACKETS |
6581 STATION_INFO_TX_RETRIES |
6582 STATION_INFO_TX_FAILED;
6583
6584 EXIT();
6585 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006586}
6587
6588static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
6589 struct net_device *dev, bool mode, v_SINT_t timeout)
6590{
6591 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05306592 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07006593 VOS_STATUS vos_status;
6594
Jeff Johnsone7245742012-09-05 17:12:55 -07006595 ENTER();
6596
Jeff Johnson295189b2012-06-20 16:38:30 -07006597 if (NULL == pAdapter)
6598 {
6599 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6600 return -ENODEV;
6601 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006602 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6603 {
6604 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6605 "%s:LOGP in Progress. Ignore!!!", __func__);
6606 return -EAGAIN;
6607 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006608
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05306609 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6610 if (NULL == pHddCtx)
6611 {
6612 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD context is NULL\n", __func__);
6613 return -ENODEV;
6614 }
6615
6616 if ((DRIVER_POWER_MODE_AUTO == !mode) &&
6617 (TRUE == pHddCtx->hdd_wlan_suspended) &&
6618 (pHddCtx->cfg_ini->fhostArpOffload) &&
6619 (eConnectionState_Associated ==
6620 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
6621 {
6622 vos_status = hdd_conf_hostarpoffload(pAdapter, TRUE);
6623 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6624 {
6625 hddLog(VOS_TRACE_LEVEL_INFO,
6626 "%s:Failed to enable ARPOFFLOAD Feature %d\n",
6627 __func__, vos_status);
6628 }
6629 }
6630
Jeff Johnson295189b2012-06-20 16:38:30 -07006631 /**The get power cmd from the supplicant gets updated by the nl only
6632 *on successful execution of the function call
6633 *we are oppositely mapped w.r.t mode in the driver
6634 **/
6635 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
6636
Jeff Johnsone7245742012-09-05 17:12:55 -07006637 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006638 if (VOS_STATUS_E_FAILURE == vos_status)
6639 {
6640 return -EINVAL;
6641 }
6642 return 0;
6643}
6644
6645
6646#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6647static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
6648 struct net_device *netdev,
6649 u8 key_index)
6650{
Jeff Johnsone7245742012-09-05 17:12:55 -07006651 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006652 return 0;
6653}
6654#endif //LINUX_VERSION_CODE
6655
6656#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
6657static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6658 struct net_device *dev,
6659 struct ieee80211_txq_params *params)
6660{
Jeff Johnsone7245742012-09-05 17:12:55 -07006661 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006662 return 0;
6663}
6664#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6665static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6666 struct ieee80211_txq_params *params)
6667{
Jeff Johnsone7245742012-09-05 17:12:55 -07006668 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006669 return 0;
6670}
6671#endif //LINUX_VERSION_CODE
6672
6673static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
6674 struct net_device *dev, u8 *mac)
6675{
6676 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006677 VOS_STATUS vos_status;
6678 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006679
Jeff Johnsone7245742012-09-05 17:12:55 -07006680 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006681 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6682 {
6683 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6684 return -EINVAL;
6685 }
6686
6687 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6688 {
6689 hddLog( LOGE,
6690 "%s: Wlan Load/Unload is in progress", __func__);
6691 return -EBUSY;
6692 }
6693
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006694 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6695 {
6696 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6697 "%s:LOGP in Progress. Ignore!!!", __func__);
6698 return -EAGAIN;
6699 }
6700
Jeff Johnson295189b2012-06-20 16:38:30 -07006701 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006702 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006703 )
6704 {
6705 if( NULL == mac )
6706 {
6707 v_U16_t i;
6708 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
6709 {
6710 if(pAdapter->aStaInfo[i].isUsed)
6711 {
6712 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
6713 hddLog(VOS_TRACE_LEVEL_INFO,
6714 "%s: Delete STA with MAC::"
6715 "%02x:%02x:%02x:%02x:%02x:%02x",
6716 __func__,
6717 macAddr[0], macAddr[1], macAddr[2],
6718 macAddr[3], macAddr[4], macAddr[5]);
6719 hdd_softap_sta_deauth(pAdapter, macAddr);
6720 }
6721 }
6722 }
6723 else
6724 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006725
6726 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
6727 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6728 {
6729 hddLog(VOS_TRACE_LEVEL_INFO,
6730 "%s: Skip this DEL STA as this is not used::"
6731 "%02x:%02x:%02x:%02x:%02x:%02x",
6732 __func__,
6733 mac[0], mac[1], mac[2],
6734 mac[3], mac[4], mac[5]);
6735 return -ENOENT;
6736 }
6737
6738 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
6739 {
6740 hddLog(VOS_TRACE_LEVEL_INFO,
6741 "%s: Skip this DEL STA as deauth is in progress::"
6742 "%02x:%02x:%02x:%02x:%02x:%02x",
6743 __func__,
6744 mac[0], mac[1], mac[2],
6745 mac[3], mac[4], mac[5]);
6746 return -ENOENT;
6747 }
6748
6749 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
6750
Jeff Johnson295189b2012-06-20 16:38:30 -07006751 hddLog(VOS_TRACE_LEVEL_INFO,
6752 "%s: Delete STA with MAC::"
6753 "%02x:%02x:%02x:%02x:%02x:%02x",
6754 __func__,
6755 mac[0], mac[1], mac[2],
6756 mac[3], mac[4], mac[5]);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006757
6758 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
6759 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6760 {
6761 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
6762 hddLog(VOS_TRACE_LEVEL_INFO,
6763 "%s: STA removal failed for ::"
6764 "%02x:%02x:%02x:%02x:%02x:%02x",
6765 __func__,
6766 mac[0], mac[1], mac[2],
6767 mac[3], mac[4], mac[5]);
6768 return -ENOENT;
6769 }
6770
Jeff Johnson295189b2012-06-20 16:38:30 -07006771 }
6772 }
6773
6774 EXIT();
6775
6776 return 0;
6777}
6778
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006779static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
6780 struct net_device *dev, u8 *mac, struct station_parameters *params)
6781{
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006782 int status = -EPERM;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006783#ifdef FEATURE_WLAN_TDLS
6784 u32 mask, set;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006785 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006786 mask = params->sta_flags_mask;
6787
6788 set = params->sta_flags_set;
6789
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006790#ifdef WLAN_FEATURE_TDLS_DEBUG
6791 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6792 "%s: mask 0x%x set 0x%x " MAC_ADDRESS_STR,
6793 __func__, mask, set, MAC_ADDR_ARRAY(mac));
6794#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006795
6796 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6797 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006798 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006799 }
6800 }
6801#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006802 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006803}
6804
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006805
6806#ifdef FEATURE_WLAN_LFR
6807static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006808 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006809{
6810#define MAX_PMKSAIDS_IN_CACHE 8
6811 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -07006812 static tANI_U32 i; // HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006813 tANI_U32 j=0;
6814 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6815 tHalHandle halHandle;
6816 eHalStatus result;
6817 tANI_U8 BSSIDMatched = 0;
6818
Jeff Johnsone7245742012-09-05 17:12:55 -07006819 ENTER();
6820
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006821 // Validate pAdapter
6822 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6823 {
6824 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6825 return -EINVAL;
6826 }
6827
6828 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6829 {
6830 hddLog( LOGE,
6831 "%s: Wlan Load/Unload is in progress", __func__);
6832 return -EBUSY;
6833 }
6834
6835 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6836 {
6837 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6838 "%s:LOGP in Progress. Ignore!!!", __func__);
6839 return -EAGAIN;
6840 }
6841
6842 // Retrieve halHandle
6843 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
6844
6845 for (j = 0; j < i; j++)
6846 {
6847 if(vos_mem_compare(PMKIDCache[j].BSSID,
6848 pmksa->bssid, WNI_CFG_BSSID_LEN))
6849 {
6850 /* BSSID matched previous entry. Overwrite it. */
6851 BSSIDMatched = 1;
6852 vos_mem_copy(PMKIDCache[j].BSSID,
6853 pmksa->bssid, WNI_CFG_BSSID_LEN);
6854 vos_mem_copy(PMKIDCache[j].PMKID,
6855 pmksa->pmkid,
6856 CSR_RSN_PMKID_SIZE);
6857 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006858 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006859 dump_bssid(pmksa->bssid);
6860 dump_pmkid(halHandle, pmksa->pmkid);
6861 break;
6862 }
6863 }
6864
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07006865 /* Check we compared all entries,if then take the first slot now */
6866 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
6867
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006868 if (!BSSIDMatched)
6869 {
6870 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
6871 vos_mem_copy(PMKIDCache[i].BSSID,
6872 pmksa->bssid, ETHER_ADDR_LEN);
6873 vos_mem_copy(PMKIDCache[i].PMKID,
6874 pmksa->pmkid,
6875 CSR_RSN_PMKID_SIZE);
6876 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006877 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006878 dump_bssid(pmksa->bssid);
6879 dump_pmkid(halHandle, pmksa->pmkid);
6880 // Increment the HDD Local Cache index
6881 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
6882 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
6883 }
6884
6885
6886 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
6887 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006888 // __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006889 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006890 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006891 // Finally set the PMKSA ID Cache in CSR
6892 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
6893 PMKIDCache,
6894 i );
6895 return 0;
6896}
6897
6898
6899static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006900 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006901{
Jeff Johnsone7245742012-09-05 17:12:55 -07006902 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006903 // TODO: Implement this later.
6904 return 0;
6905}
6906
6907static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
6908{
Jeff Johnsone7245742012-09-05 17:12:55 -07006909 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006910 // TODO: Implement this later.
6911 return 0;
6912}
6913#endif
6914
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006915#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6916static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
6917 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
6918{
6919 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6920 hdd_station_ctx_t *pHddStaCtx;
6921
6922 if (NULL == pAdapter)
6923 {
6924 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6925 return -ENODEV;
6926 }
6927
6928 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6929
6930 // Added for debug on reception of Re-assoc Req.
6931 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6932 {
6933 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
6934 ftie->ie_len);
6935 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
6936 }
6937
6938#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
6939 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
6940 ftie->ie_len);
6941#endif
6942
6943 // Pass the received FT IEs to SME
Gopichand Nakkala356fb102013-03-06 12:34:04 +05306944 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6945 (const u8 *)ftie->ie,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006946 ftie->ie_len);
6947 return 0;
6948}
6949#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006950
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006951#ifdef FEATURE_WLAN_TDLS
6952static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
6953 u8 *peer, u8 action_code, u8 dialog_token,
6954 u16 status_code, const u8 *buf, size_t len)
6955{
6956
6957 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6958 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006959 u8 peerMac[6];
6960 VOS_STATUS status;
Gopichand Nakkala05922802013-03-14 12:23:19 -07006961 int max_sta_failed = 0;
Hoonki Leea34dd892013-02-05 22:56:02 -08006962 int responder;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006963
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006964 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006965 {
6966 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6967 "Invalid arguments");
6968 return -EINVAL;
6969 }
6970
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006971 if (pHddCtx->isLogpInProgress)
6972 {
6973 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6974 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006975 wlan_hdd_tdls_set_link_status(pAdapter, peer, eTDLS_LINK_IDLE);
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006976 return -EBUSY;
6977 }
6978
Hoonki Lee27511902013-03-14 18:19:06 -07006979 if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006980 {
Hoonki Lee27511902013-03-14 18:19:06 -07006981 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6982 "%s: TDLS mode is disabled OR not enabled in FW."
6983 MAC_ADDRESS_STR " action %d declined.",
6984 __func__, MAC_ADDR_ARRAY(peer), action_code);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006985 return -ENOTSUPP;
6986 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006987
Hoonki Lee27511902013-03-14 18:19:06 -07006988 /* other than teardown frame, other mgmt frames are not sent if disabled */
6989 if (SIR_MAC_TDLS_TEARDOWN != action_code)
6990 {
6991 /* if tdls_mode is disabled to respond to peer's request */
6992 if (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode)
6993 {
6994 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6995 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006996 " TDLS mode is disabled. action %d declined.",
6997 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee27511902013-03-14 18:19:06 -07006998
6999 return -ENOTSUPP;
7000 }
7001 }
7002
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007003 if (WLAN_IS_TDLS_SETUP_ACTION(action_code))
7004 {
Hoonki Leefb8df672013-04-10 18:20:34 -07007005 if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, peer, TRUE, TRUE))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007006 {
7007 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007008 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07007009 " TDLS setup is ongoing. action %d declined.",
7010 __func__, MAC_ADDR_ARRAY(peer), action_code);
7011 return -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007012 }
7013 }
7014
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007015 if (SIR_MAC_TDLS_SETUP_REQ == action_code ||
7016 SIR_MAC_TDLS_SETUP_RSP == action_code )
Lee Hoonkic1262f22013-01-24 21:59:00 -08007017 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007018 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
Lee Hoonkic1262f22013-01-24 21:59:00 -08007019 {
7020 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
7021 we return error code at 'add_station()'. Hence we have this
7022 check again in addtion to add_station().
7023 Anyway, there is no hard to double-check. */
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007024 if (SIR_MAC_TDLS_SETUP_REQ == action_code)
Lee Hoonkic1262f22013-01-24 21:59:00 -08007025 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007026 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7027 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07007028 " TDLS Max peer already connected. action %d declined.",
7029 __func__, MAC_ADDR_ARRAY(peer), action_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07007030 goto error;
Lee Hoonkic1262f22013-01-24 21:59:00 -08007031 }
7032 else
7033 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007034 /* maximum reached. tweak to send error code to peer and return
7035 error code to supplicant */
Lee Hoonkic1262f22013-01-24 21:59:00 -08007036 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007037 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7038 "%s: " MAC_ADDRESS_STR
7039 " TDLS Max peer already connected send response status %d",
7040 __func__, MAC_ADDR_ARRAY(peer), status_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07007041 max_sta_failed = -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007042 /* fall through to send setup resp with failure status
7043 code */
Lee Hoonkic1262f22013-01-24 21:59:00 -08007044 }
7045 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007046 else
7047 {
7048 hddTdlsPeer_t *pTdlsPeer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007049 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007050 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007051 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007052 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07007053 "%s:" MAC_ADDRESS_STR " already connected. action %d declined.",
7054 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007055 return -EPERM;
7056 }
7057 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08007058 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007059 vos_mem_copy(peerMac, peer, 6);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007060
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007061#ifdef WLAN_FEATURE_TDLS_DEBUG
7062 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007063 "%s: " MAC_ADDRESS_STR " action %d, dialog_token %d status %d, len = %d",
7064 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
7065 action_code, dialog_token, status_code, len);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007066#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007067
Hoonki Leea34dd892013-02-05 22:56:02 -08007068 /*Except teardown responder will not be used so just make 0*/
7069 responder = 0;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007070 if (SIR_MAC_TDLS_TEARDOWN == action_code)
Hoonki Leea34dd892013-02-05 22:56:02 -08007071 {
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -07007072
7073 hddTdlsPeer_t *pTdlsPeer;
7074 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peerMac);
7075
7076 if(pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
7077 responder = pTdlsPeer->is_responder;
7078 else
Hoonki Leea34dd892013-02-05 22:56:02 -08007079 {
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -07007080 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7081 "%s: " MAC_ADDRESS_STR " peer doesn't exist or not connected %d dialog_token %d status %d, len = %d",
7082 __func__, MAC_ADDR_ARRAY(peer), (NULL == pTdlsPeer) ? -1 : pTdlsPeer->link_status,
7083 dialog_token, status_code, len);
7084 return -EPERM;
Hoonki Leea34dd892013-02-05 22:56:02 -08007085 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007086 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007087
Hoonki Lee14621352013-04-16 17:51:19 -07007088 if ((SIR_MAC_TDLS_SETUP_RSP == action_code) ||
7089 (SIR_MAC_TDLS_DIS_RSP == action_code))
7090 {
7091 if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter)))
7092 {
7093 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
7094 "%s: Sending Disc/Setup Rsp Frame.Disable BMPS", __func__);
7095 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
7096 }
7097 wlan_hdd_tdls_set_cap(pAdapter, peerMac, eTDLS_CAP_SUPPORTED);
7098 }
7099
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007100 INIT_COMPLETION(pAdapter->tdls_mgmt_comp);
7101
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007102 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
Hoonki Leea34dd892013-02-05 22:56:02 -08007103 peerMac, action_code, dialog_token, status_code, (tANI_U8 *)buf, len, responder);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007104
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007105 if (VOS_STATUS_SUCCESS != status)
7106 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007107 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7108 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
Hoonki Lee14621352013-04-16 17:51:19 -07007109 wlan_hdd_tdls_check_bmps(pAdapter);
7110 goto error;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007111 }
7112
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08007113 /* not block discovery request, as it is called from timer callback */
7114 if (SIR_MAC_TDLS_DIS_REQ != action_code)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007115 {
Pervinder Singhb4638422013-03-04 22:51:36 -08007116 long rc;
7117
7118 rc = wait_for_completion_interruptible_timeout(&pAdapter->tdls_mgmt_comp,
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08007119 msecs_to_jiffies(WAIT_TIME_TDLS_MGMT));
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007120
Pervinder Singhb4638422013-03-04 22:51:36 -08007121 if ((rc <= 0) || (TRUE != pAdapter->mgmtTxCompletionStatus))
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08007122 {
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08007123 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pervinder Singhb4638422013-03-04 22:51:36 -08007124 "%s: Mgmt Tx Completion failed status %ld TxCompletion %lu",
7125 __func__, rc, pAdapter->mgmtTxCompletionStatus);
Hoonki Lee14621352013-04-16 17:51:19 -07007126 wlan_hdd_tdls_check_bmps(pAdapter);
Hoonki Leefb8df672013-04-10 18:20:34 -07007127 goto error;
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08007128 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007129 }
7130
Gopichand Nakkala05922802013-03-14 12:23:19 -07007131 if (max_sta_failed)
Hoonki Lee14621352013-04-16 17:51:19 -07007132 {
7133 wlan_hdd_tdls_check_bmps(pAdapter);
Gopichand Nakkala05922802013-03-14 12:23:19 -07007134 return max_sta_failed;
Hoonki Lee14621352013-04-16 17:51:19 -07007135 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007136
Hoonki Leea34dd892013-02-05 22:56:02 -08007137 if (SIR_MAC_TDLS_SETUP_RSP == action_code)
7138 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007139 wlan_hdd_tdls_set_responder(pAdapter, peerMac, TRUE);
Hoonki Leea34dd892013-02-05 22:56:02 -08007140 }
7141 else if (SIR_MAC_TDLS_SETUP_CNF == action_code)
7142 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007143 wlan_hdd_tdls_set_responder(pAdapter, peerMac, FALSE);
Hoonki Leea34dd892013-02-05 22:56:02 -08007144 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007145
7146 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07007147error:
7148 /* max_sta_failed ; we didn't set to CONNECTING for this case,
7149 because we already know that this transaction will be failed,
7150 but we weren't sure if supplicant call DISABLE_LINK or not. So,
7151 to be safe, do not change the state mahine.
7152 */
7153 if(max_sta_failed == 0 &&
7154 (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
7155 wlan_hdd_tdls_set_link_status(pAdapter, peerMac, eTDLS_LINK_IDLE);
7156 return -EPERM;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007157}
7158
7159static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
7160 u8 *peer, enum nl80211_tdls_operation oper)
7161{
7162 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7163 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007164#ifdef WLAN_FEATURE_TDLS_DEBUG
7165 const char *tdls_oper_str[]= {
7166 "NL80211_TDLS_DISCOVERY_REQ",
7167 "NL80211_TDLS_SETUP",
7168 "NL80211_TDLS_TEARDOWN",
7169 "NL80211_TDLS_ENABLE_LINK",
7170 "NL80211_TDLS_DISABLE_LINK",
7171 "NL80211_TDLS_UNKONW_OPER"};
7172#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007173
Chilam Ngc4244af2013-04-01 15:37:32 -07007174 if ( NULL == pHddCtx || NULL == pHddCtx->cfg_ini || NULL == peer )
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007175 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007176 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Chilam Ngc4244af2013-04-01 15:37:32 -07007177 "%s: Invalid arguments", __func__);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007178 return -EINVAL;
7179 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007180
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08007181 if (pHddCtx->isLogpInProgress)
7182 {
7183 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7184 "%s:LOGP in Progress. Ignore!!!", __func__);
7185 return -EBUSY;
7186 }
7187
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007188#ifdef WLAN_FEATURE_TDLS_DEBUG
7189 if((int)oper > 4)
7190 oper = 5;
7191
7192 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007193 "%s: " MAC_ADDRESS_STR " %d (%s) ", "tdls_oper",
7194 MAC_ADDR_ARRAY(peer), (int)oper,
7195 tdls_oper_str[(int)oper]);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007196#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007197
7198 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007199 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007200 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007201 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Chilam Ngc4244af2013-04-01 15:37:32 -07007202 "TDLS Disabled in INI OR not enabled in FW. "
7203 "Cannot process TDLS commands");
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007204 return -ENOTSUPP;
7205 }
7206
7207 switch (oper) {
7208 case NL80211_TDLS_ENABLE_LINK:
7209 {
Hoonki Lee387663d2013-02-05 18:08:43 -08007210 hddTdlsPeer_t *pTdlsPeer;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007211 VOS_STATUS status;
7212
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007213 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007214
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007215 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
7216 "%s: TDLS_LINK_ENABLE " MAC_ADDRESS_STR,
7217 __func__, MAC_ADDR_ARRAY(peer));
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007218
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007219 if ( NULL == pTdlsPeer ) {
7220 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_hdd_tdls_find_peer "
7221 MAC_ADDRESS_STR " failed",
7222 __func__, MAC_ADDR_ARRAY(peer));
7223 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007224 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007225
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007226 if (eTDLS_LINK_CONNECTING == pTdlsPeer->link_status)
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007227 {
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007228 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007229 /* start TDLS client registration with TL */
7230 status = hdd_roamRegisterTDLSSTA( pAdapter, peer, pTdlsPeer->staId, pTdlsPeer->signature);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007231 if (VOS_STATUS_SUCCESS == status)
7232 {
Hoonki Lee14621352013-04-16 17:51:19 -07007233 if (pTdlsPeer->is_responder == 0)
7234 {
7235 v_U8_t staId = (v_U8_t)pTdlsPeer->staId;
7236
7237 wlan_hdd_tdls_timer_restart(pAdapter,
7238 &pTdlsPeer->initiatorWaitTimeoutTimer,
7239 WAIT_TIME_TDLS_INITIATOR);
7240 /* suspend initiator TX until it receives direct packet from the
7241 reponder or WAIT_TIME_TDLS_INITIATOR timer expires */
7242 WLANTL_SuspendDataTx( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
7243 &staId, NULL);
7244 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007245 wlan_hdd_tdls_increment_peer_count(pAdapter);
7246 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007247 wlan_hdd_tdls_check_bmps(pAdapter);
7248 }
7249
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007250 }
7251 break;
7252 case NL80211_TDLS_DISABLE_LINK:
Lee Hoonkic1262f22013-01-24 21:59:00 -08007253 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007254 hddTdlsPeer_t *curr_peer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007255
7256 if(NULL != curr_peer)
Lee Hoonkic1262f22013-01-24 21:59:00 -08007257 {
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007258 long status;
7259
7260 INIT_COMPLETION(pAdapter->tdls_del_station_comp);
7261
Lee Hoonkic1262f22013-01-24 21:59:00 -08007262 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
7263 pAdapter->sessionId, peer );
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007264
7265 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_del_station_comp,
7266 msecs_to_jiffies(WAIT_TIME_TDLS_DEL_STA));
7267 if (status <= 0)
7268 {
7269 wlan_hdd_tdls_set_peer_link_status(curr_peer, eTDLS_LINK_IDLE);
7270 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7271 "%s: Del station failed status %ld",
7272 __func__, status);
7273 return -EPERM;
7274 }
Gopichand Nakkala8b00c632013-03-08 19:47:52 -08007275 wlan_hdd_tdls_set_peer_link_status(curr_peer, eTDLS_LINK_IDLE);
Lee Hoonkic1262f22013-01-24 21:59:00 -08007276 }
7277 else
7278 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007279 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7280 "%s: TDLS Peer Station doesn't exist.", __func__);
Lee Hoonkic1262f22013-01-24 21:59:00 -08007281 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08007282 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007283 break;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007284 case NL80211_TDLS_TEARDOWN:
7285 case NL80211_TDLS_SETUP:
7286 case NL80211_TDLS_DISCOVERY_REQ:
7287 /* We don't support in-driver setup/teardown/discovery */
7288 return -ENOTSUPP;
7289 default:
7290 return -ENOTSUPP;
7291 }
7292 return 0;
7293}
Chilam NG571c65a2013-01-19 12:27:36 +05307294
7295int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
7296 struct net_device *dev, u8 *peer)
7297{
7298 hddLog(VOS_TRACE_LEVEL_INFO, "tdls send discover req: %x %x %x %x %x %x",
7299 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5]);
7300
7301 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
7302 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
7303}
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007304#endif
7305
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05307306#ifdef WLAN_FEATURE_GTK_OFFLOAD
7307/*
7308 * FUNCTION: wlan_hdd_cfg80211_update_replayCounterCallback
7309 * Callback rountine called upon receiving response for
7310 * get offload info
7311 */
7312void wlan_hdd_cfg80211_update_replayCounterCallback(void *callbackContext,
7313 tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoRsp)
7314{
7315
7316 hdd_adapter_t *pAdapter = (hdd_adapter_t *)callbackContext;
7317
7318 ENTER();
7319
7320 if (NULL == pAdapter)
7321 {
7322 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7323 "%s: HDD adapter is Null", __func__);
7324 return ;
7325 }
7326
7327 if (NULL == pGtkOffloadGetInfoRsp)
7328 {
7329 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7330 "%s: pGtkOffloadGetInfoRsp is Null", __func__);
7331 return ;
7332 }
7333
7334 if (VOS_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus)
7335 {
7336 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7337 "%s: wlan Failed to get replay counter value",
7338 __func__);
7339 return ;
7340 }
7341
7342 /* Update replay counter to NL */
7343 cfg80211_gtk_rekey_notify(pAdapter->dev, pGtkOffloadGetInfoRsp->bssId,
7344 (tANI_U8 *)&pGtkOffloadGetInfoRsp->ullKeyReplayCounter, GFP_KERNEL);
7345}
7346
7347/*
7348 * FUNCTION: wlan_hdd_cfg80211_set_rekey_data
7349 * This function is used to offload GTK rekeying job to the firmware.
7350 */
7351int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
7352 struct cfg80211_gtk_rekey_data *data)
7353{
7354 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7355 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
7356 hdd_station_ctx_t *pHddStaCtx;
7357 tHalHandle hHal;
7358 tpSirGtkOffloadParams pGtkOffloadReqParams;
7359 eHalStatus status = eHAL_STATUS_FAILURE;
7360
7361 ENTER();
7362
7363 if (NULL == pAdapter)
7364 {
7365 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7366 "%s: HDD adapter is Null", __func__);
7367 return -ENODEV;
7368 }
7369
7370 if (NULL == pHddCtx)
7371 {
7372 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7373 "%s: HDD context is Null!!!", __func__);
7374 return -ENODEV;
7375 }
7376
7377 if (pHddCtx->isLogpInProgress)
7378 {
7379 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7380 "%s: LOGP in Progress. Ignore!!!", __func__);
7381 return -EAGAIN;
7382 }
7383
7384 if (pHddCtx->isLoadUnloadInProgress)
7385 {
7386 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7387 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
7388 return -EAGAIN;
7389 }
7390
7391 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7392 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
7393 if (NULL == hHal)
7394 {
7395 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7396 "%s: HAL context is Null!!!", __func__);
7397 return -EAGAIN;
7398 }
7399
7400 pGtkOffloadReqParams =
7401 &pHddStaCtx->gtkOffloadRequestParams.gtkOffloadReqParams;
7402
7403 pGtkOffloadReqParams->ulFlags = GTK_OFFLOAD_ENABLE;
7404 memcpy(pGtkOffloadReqParams->aKCK, data->kck, NL80211_KCK_LEN);
7405 memcpy(pGtkOffloadReqParams->aKEK, data->kek, NL80211_KEK_LEN);
7406 memcpy(pGtkOffloadReqParams->bssId, &pHddStaCtx->conn_info.bssId,
7407 WNI_CFG_BSSID_LEN);
7408 memcpy(&pGtkOffloadReqParams->ullKeyReplayCounter, &data->replay_ctr,
7409 sizeof (tANI_U64));
7410
7411 if (TRUE == pHddCtx->hdd_wlan_suspended)
7412 {
7413 /* if wlan is suspended, enable GTK offload directly from here */
7414 status = sme_SetGTKOffload(hHal, pGtkOffloadReqParams,
7415 pAdapter->sessionId);
7416
7417 if (eHAL_STATUS_SUCCESS != status)
7418 {
7419 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7420 "%s: sme_SetGTKOffload failed, returned %d",
7421 __func__, status);
7422 return status;
7423 }
7424 pHddStaCtx->gtkOffloadRequestParams.requested = FALSE;
7425 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7426 "%s: sme_SetGTKOffload successfull", __func__);
7427 }
7428 else
7429 {
7430 pHddStaCtx->gtkOffloadRequestParams.requested = TRUE;
7431 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7432 "%s: wlan not suspended GTKOffload request is stored",
7433 __func__);
7434 return eHAL_STATUS_SUCCESS;
7435 }
7436 return status;
7437}
7438#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
7439
Jeff Johnson295189b2012-06-20 16:38:30 -07007440/* cfg80211_ops */
7441static struct cfg80211_ops wlan_hdd_cfg80211_ops =
7442{
7443 .add_virtual_intf = wlan_hdd_add_virtual_intf,
7444 .del_virtual_intf = wlan_hdd_del_virtual_intf,
7445 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
7446 .change_station = wlan_hdd_change_station,
7447#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
7448 .add_beacon = wlan_hdd_cfg80211_add_beacon,
7449 .del_beacon = wlan_hdd_cfg80211_del_beacon,
7450 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007451#else
7452 .start_ap = wlan_hdd_cfg80211_start_ap,
7453 .change_beacon = wlan_hdd_cfg80211_change_beacon,
7454 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07007455#endif
7456 .change_bss = wlan_hdd_cfg80211_change_bss,
7457 .add_key = wlan_hdd_cfg80211_add_key,
7458 .get_key = wlan_hdd_cfg80211_get_key,
7459 .del_key = wlan_hdd_cfg80211_del_key,
7460 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08007461#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07007462 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08007463#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007464 .scan = wlan_hdd_cfg80211_scan,
7465 .connect = wlan_hdd_cfg80211_connect,
7466 .disconnect = wlan_hdd_cfg80211_disconnect,
7467 .join_ibss = wlan_hdd_cfg80211_join_ibss,
7468 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
7469 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
7470 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
7471 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
Jeff Johnson295189b2012-06-20 16:38:30 -07007472 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
7473 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
7474 .mgmt_tx = wlan_hdd_action,
7475#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7476 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
7477 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
7478 .set_txq_params = wlan_hdd_set_txq_params,
7479#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007480 .get_station = wlan_hdd_cfg80211_get_station,
7481 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
7482 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007483 .add_station = wlan_hdd_cfg80211_add_station,
7484#ifdef FEATURE_WLAN_LFR
7485 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
7486 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
7487 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
7488#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007489#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
7490 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
7491#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007492#ifdef FEATURE_WLAN_TDLS
7493 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
7494 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
7495#endif
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05307496#ifdef WLAN_FEATURE_GTK_OFFLOAD
7497 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
7498#endif /* WLAN_FEATURE_GTK_OFFLOAD */
Jeff Johnson295189b2012-06-20 16:38:30 -07007499};
7500