blob: 489b55abf025d1754b27c7fdd287ea88c1c445ce [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/**========================================================================
43
44 \file wlan_hdd_cfg80211.c
45
46 \brief WLAN Host Device Driver implementation
47
48 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
49
50 Qualcomm Confidential and Proprietary.
51
52 ========================================================================*/
53
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070054/**=========================================================================
Jeff Johnson295189b2012-06-20 16:38:30 -070055
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070056 EDIT HISTORY FOR FILE
Jeff Johnson295189b2012-06-20 16:38:30 -070057
58
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070059 This section contains comments describing changes made to the module.
60 Notice that changes are listed in reverse chronological order.
Jeff Johnson295189b2012-06-20 16:38:30 -070061
62
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070063 $Header:$ $DateTime: $ $Author: $
Jeff Johnson295189b2012-06-20 16:38:30 -070064
65
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070066 when who what, where, why
Jeff Johnson295189b2012-06-20 16:38:30 -070067 -------- --- --------------------------------------------------------
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070068 21/12/09 Ashwani Created module.
Jeff Johnson295189b2012-06-20 16:38:30 -070069
70 07/06/10 Kumar Deepak Implemented cfg80211 callbacks for ANDROID
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070071 Ganesh K
Jeff Johnson295189b2012-06-20 16:38:30 -070072 ==========================================================================*/
73
Jeff Johnson295189b2012-06-20 16:38:30 -070074
75#include <linux/version.h>
76#include <linux/module.h>
77#include <linux/kernel.h>
78#include <linux/init.h>
79#include <linux/wireless.h>
80#include <wlan_hdd_includes.h>
81#include <net/arp.h>
82#include <net/cfg80211.h>
83#include <linux/wireless.h>
84#include <wlan_hdd_wowl.h>
85#include <aniGlobal.h>
86#include "ccmApi.h"
87#include "sirParams.h"
88#include "dot11f.h"
89#include "wlan_hdd_assoc.h"
90#include "wlan_hdd_wext.h"
91#include "sme_Api.h"
92#include "wlan_hdd_p2p.h"
93#include "wlan_hdd_cfg80211.h"
94#include "wlan_hdd_hostapd.h"
95#include "sapInternal.h"
96#include "wlan_hdd_softap_tx_rx.h"
97#include "wlan_hdd_main.h"
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +053098#include "wlan_hdd_assoc.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070099#ifdef WLAN_BTAMP_FEATURE
100#include "bap_hdd_misc.h"
101#endif
102#include <qc_sap_ioctl.h>
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800103#ifdef FEATURE_WLAN_TDLS
104#include "wlan_hdd_tdls.h"
105#endif
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +0530106#include "wlan_nv.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700107
108#define g_mode_rates_size (12)
109#define a_mode_rates_size (8)
110#define FREQ_BASE_80211G (2407)
111#define FREQ_BAND_DIFF_80211G (5)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700112#define MAX_SCAN_SSID 9
Jeff Johnson295189b2012-06-20 16:38:30 -0700113#define GET_IE_LEN_IN_BSS_DESC(lenInBss) ( lenInBss + sizeof(lenInBss) - \
114 ((int) OFFSET_OF( tSirBssDescription, ieFields)))
115
116#define HDD2GHZCHAN(freq, chan, flag) { \
117 .band = IEEE80211_BAND_2GHZ, \
118 .center_freq = (freq), \
119 .hw_value = (chan),\
120 .flags = (flag), \
121 .max_antenna_gain = 0 ,\
122 .max_power = 30, \
123}
124
125#define HDD5GHZCHAN(freq, chan, flag) { \
126 .band = IEEE80211_BAND_5GHZ, \
127 .center_freq = (freq), \
128 .hw_value = (chan),\
129 .flags = (flag), \
130 .max_antenna_gain = 0 ,\
131 .max_power = 30, \
132}
133
134#define HDD_G_MODE_RATETAB(rate, rate_id, flag)\
135{\
136 .bitrate = rate, \
137 .hw_value = rate_id, \
138 .flags = flag, \
139}
140
Lee Hoonkic1262f22013-01-24 21:59:00 -0800141#ifndef WLAN_FEATURE_TDLS_DEBUG
142#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_INFO
143#else
144#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_ERROR
145#endif
146
Gopichand Nakkala356fb102013-03-06 12:34:04 +0530147#ifdef WLAN_FEATURE_VOWIFI_11R
148#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
149#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
150#endif
151
Jeff Johnson295189b2012-06-20 16:38:30 -0700152static const u32 hdd_cipher_suites[] =
153{
154 WLAN_CIPHER_SUITE_WEP40,
155 WLAN_CIPHER_SUITE_WEP104,
156 WLAN_CIPHER_SUITE_TKIP,
157#ifdef FEATURE_WLAN_CCX
158#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
159 WLAN_CIPHER_SUITE_KRK,
160 WLAN_CIPHER_SUITE_CCMP,
161#else
162 WLAN_CIPHER_SUITE_CCMP,
163#endif
164#ifdef FEATURE_WLAN_WAPI
165 WLAN_CIPHER_SUITE_SMS4,
166#endif
Chet Lanctot186b5732013-03-18 10:26:30 -0700167#ifdef WLAN_FEATURE_11W
168 WLAN_CIPHER_SUITE_AES_CMAC,
169#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700170};
171
172static inline int is_broadcast_ether_addr(const u8 *addr)
173{
174 return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&
175 (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
176}
177
178static struct ieee80211_channel hdd_channels_2_4_GHZ[] =
179{
180 HDD2GHZCHAN(2412, 1, 0) ,
181 HDD2GHZCHAN(2417, 2, 0) ,
182 HDD2GHZCHAN(2422, 3, 0) ,
183 HDD2GHZCHAN(2427, 4, 0) ,
184 HDD2GHZCHAN(2432, 5, 0) ,
185 HDD2GHZCHAN(2437, 6, 0) ,
186 HDD2GHZCHAN(2442, 7, 0) ,
187 HDD2GHZCHAN(2447, 8, 0) ,
188 HDD2GHZCHAN(2452, 9, 0) ,
189 HDD2GHZCHAN(2457, 10, 0) ,
190 HDD2GHZCHAN(2462, 11, 0) ,
191 HDD2GHZCHAN(2467, 12, 0) ,
192 HDD2GHZCHAN(2472, 13, 0) ,
193 HDD2GHZCHAN(2484, 14, 0) ,
194};
195
Jeff Johnson295189b2012-06-20 16:38:30 -0700196static struct ieee80211_channel hdd_social_channels_2_4_GHZ[] =
197{
198 HDD2GHZCHAN(2412, 1, 0) ,
199 HDD2GHZCHAN(2437, 6, 0) ,
200 HDD2GHZCHAN(2462, 11, 0) ,
201};
Jeff Johnson295189b2012-06-20 16:38:30 -0700202
203static struct ieee80211_channel hdd_channels_5_GHZ[] =
204{
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700205 HDD5GHZCHAN(4920, 240, 0) ,
206 HDD5GHZCHAN(4940, 244, 0) ,
207 HDD5GHZCHAN(4960, 248, 0) ,
208 HDD5GHZCHAN(4980, 252, 0) ,
209 HDD5GHZCHAN(5040, 208, 0) ,
210 HDD5GHZCHAN(5060, 212, 0) ,
211 HDD5GHZCHAN(5080, 216, 0) ,
Jeff Johnson295189b2012-06-20 16:38:30 -0700212 HDD5GHZCHAN(5180, 36, 0) ,
213 HDD5GHZCHAN(5200, 40, 0) ,
214 HDD5GHZCHAN(5220, 44, 0) ,
215 HDD5GHZCHAN(5240, 48, 0) ,
216 HDD5GHZCHAN(5260, 52, 0) ,
217 HDD5GHZCHAN(5280, 56, 0) ,
218 HDD5GHZCHAN(5300, 60, 0) ,
219 HDD5GHZCHAN(5320, 64, 0) ,
220 HDD5GHZCHAN(5500,100, 0) ,
221 HDD5GHZCHAN(5520,104, 0) ,
222 HDD5GHZCHAN(5540,108, 0) ,
223 HDD5GHZCHAN(5560,112, 0) ,
224 HDD5GHZCHAN(5580,116, 0) ,
225 HDD5GHZCHAN(5600,120, 0) ,
226 HDD5GHZCHAN(5620,124, 0) ,
227 HDD5GHZCHAN(5640,128, 0) ,
228 HDD5GHZCHAN(5660,132, 0) ,
229 HDD5GHZCHAN(5680,136, 0) ,
230 HDD5GHZCHAN(5700,140, 0) ,
231 HDD5GHZCHAN(5745,149, 0) ,
232 HDD5GHZCHAN(5765,153, 0) ,
233 HDD5GHZCHAN(5785,157, 0) ,
234 HDD5GHZCHAN(5805,161, 0) ,
235 HDD5GHZCHAN(5825,165, 0) ,
236};
237
238static struct ieee80211_rate g_mode_rates[] =
239{
240 HDD_G_MODE_RATETAB(10, 0x1, 0),
241 HDD_G_MODE_RATETAB(20, 0x2, 0),
242 HDD_G_MODE_RATETAB(55, 0x4, 0),
243 HDD_G_MODE_RATETAB(110, 0x8, 0),
244 HDD_G_MODE_RATETAB(60, 0x10, 0),
245 HDD_G_MODE_RATETAB(90, 0x20, 0),
246 HDD_G_MODE_RATETAB(120, 0x40, 0),
247 HDD_G_MODE_RATETAB(180, 0x80, 0),
248 HDD_G_MODE_RATETAB(240, 0x100, 0),
249 HDD_G_MODE_RATETAB(360, 0x200, 0),
250 HDD_G_MODE_RATETAB(480, 0x400, 0),
251 HDD_G_MODE_RATETAB(540, 0x800, 0),
252};
253
254static struct ieee80211_rate a_mode_rates[] =
255{
256 HDD_G_MODE_RATETAB(60, 0x10, 0),
257 HDD_G_MODE_RATETAB(90, 0x20, 0),
258 HDD_G_MODE_RATETAB(120, 0x40, 0),
259 HDD_G_MODE_RATETAB(180, 0x80, 0),
260 HDD_G_MODE_RATETAB(240, 0x100, 0),
261 HDD_G_MODE_RATETAB(360, 0x200, 0),
262 HDD_G_MODE_RATETAB(480, 0x400, 0),
263 HDD_G_MODE_RATETAB(540, 0x800, 0),
264};
265
266static struct ieee80211_supported_band wlan_hdd_band_2_4_GHZ =
267{
268 .channels = hdd_channels_2_4_GHZ,
269 .n_channels = ARRAY_SIZE(hdd_channels_2_4_GHZ),
270 .band = IEEE80211_BAND_2GHZ,
271 .bitrates = g_mode_rates,
272 .n_bitrates = g_mode_rates_size,
273 .ht_cap.ht_supported = 1,
274 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
275 | IEEE80211_HT_CAP_GRN_FLD
276 | IEEE80211_HT_CAP_DSSSCCK40
277 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
278 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
279 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
280 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
281 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
282 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
283};
284
Jeff Johnson295189b2012-06-20 16:38:30 -0700285static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_GHZ =
286{
287 .channels = hdd_social_channels_2_4_GHZ,
288 .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_GHZ),
289 .band = IEEE80211_BAND_2GHZ,
290 .bitrates = g_mode_rates,
291 .n_bitrates = g_mode_rates_size,
292 .ht_cap.ht_supported = 1,
293 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
294 | IEEE80211_HT_CAP_GRN_FLD
295 | IEEE80211_HT_CAP_DSSSCCK40
296 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
297 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
298 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
299 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
300 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
301 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
302};
Jeff Johnson295189b2012-06-20 16:38:30 -0700303
304static struct ieee80211_supported_band wlan_hdd_band_5_GHZ =
305{
306 .channels = hdd_channels_5_GHZ,
307 .n_channels = ARRAY_SIZE(hdd_channels_5_GHZ),
308 .band = IEEE80211_BAND_5GHZ,
309 .bitrates = a_mode_rates,
310 .n_bitrates = a_mode_rates_size,
311 .ht_cap.ht_supported = 1,
312 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
313 | IEEE80211_HT_CAP_GRN_FLD
314 | IEEE80211_HT_CAP_DSSSCCK40
315 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
316 | IEEE80211_HT_CAP_SGI_40
317 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
318 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
319 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
320 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
321 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
322 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
323};
324
325/* This structure contain information what kind of frame are expected in
326 TX/RX direction for each kind of interface */
327static const struct ieee80211_txrx_stypes
328wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
329 [NL80211_IFTYPE_STATION] = {
330 .tx = 0xffff,
331 .rx = BIT(SIR_MAC_MGMT_ACTION) |
332 BIT(SIR_MAC_MGMT_PROBE_REQ),
333 },
334 [NL80211_IFTYPE_AP] = {
335 .tx = 0xffff,
336 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
337 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
338 BIT(SIR_MAC_MGMT_PROBE_REQ) |
339 BIT(SIR_MAC_MGMT_DISASSOC) |
340 BIT(SIR_MAC_MGMT_AUTH) |
341 BIT(SIR_MAC_MGMT_DEAUTH) |
342 BIT(SIR_MAC_MGMT_ACTION),
343 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700344 [NL80211_IFTYPE_P2P_CLIENT] = {
345 .tx = 0xffff,
346 .rx = BIT(SIR_MAC_MGMT_ACTION) |
347 BIT(SIR_MAC_MGMT_PROBE_REQ),
348 },
349 [NL80211_IFTYPE_P2P_GO] = {
350 /* This is also same as for SoftAP */
351 .tx = 0xffff,
352 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
353 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
354 BIT(SIR_MAC_MGMT_PROBE_REQ) |
355 BIT(SIR_MAC_MGMT_DISASSOC) |
356 BIT(SIR_MAC_MGMT_AUTH) |
357 BIT(SIR_MAC_MGMT_DEAUTH) |
358 BIT(SIR_MAC_MGMT_ACTION),
359 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700360};
361
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800362#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800363static const struct ieee80211_iface_limit
364wlan_hdd_iface_limit[] = {
365 {
Sunil Ravia72c3992013-01-31 06:12:22 -0800366 /* max = 3 ; Our driver create two interfaces during driver init
367 * wlan0 and p2p0 interfaces. p2p0 is considered as station
368 * interface until a group is formed. In JB architecture, once the
369 * group is formed, interface type of p2p0 is changed to P2P GO or
370 * Client.
371 * When supplicant remove the group, it first issue a set interface
372 * cmd to change the mode back to Station. In JB this works fine as
373 * we advertize two station type interface during driver init.
374 * Some vendors create separate interface for P2P GO/Client,
375 * after group formation(Third one). But while group remove
376 * supplicant first tries to change the mode(3rd interface) to STATION
377 * But as we advertized only two sta type interfaces nl80211 was
378 * returning error for the third one which was leading to failure in
379 * delete interface. Ideally while removing the group, supplicant
380 * should not try to change the 3rd interface mode to Station type.
381 * Till we get a fix in wpa_supplicant, we advertize max STA
382 * interface type to 3
383 */
384 .max = 3,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800385 .types = BIT(NL80211_IFTYPE_STATION),
386 },
387 {
388 .max = 1,
389 .types = BIT(NL80211_IFTYPE_AP),
390 },
391 {
392 .max = 1,
393 .types = BIT(NL80211_IFTYPE_P2P_GO) |
394 BIT(NL80211_IFTYPE_P2P_CLIENT),
395 },
396};
397
398/* By default, only single channel concurrency is allowed */
399static struct ieee80211_iface_combination
400wlan_hdd_iface_combination = {
401 .limits = wlan_hdd_iface_limit,
402 .num_different_channels = 1,
Sunil Ravia72c3992013-01-31 06:12:22 -0800403 /*
404 * max = WLAN_MAX_INTERFACES ; JellyBean architecture creates wlan0
405 * and p2p0 interfaces during driver init
406 * Some vendors create separate interface for P2P operations.
407 * wlan0: STA interface
408 * p2p0: P2P Device interface, action frames goes
409 * through this interface.
410 * p2p-xx: P2P interface, After GO negotiation this interface is
411 * created for p2p operations(GO/CLIENT interface).
412 */
413 .max_interfaces = WLAN_MAX_INTERFACES,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800414 .n_limits = ARRAY_SIZE(wlan_hdd_iface_limit),
415 .beacon_int_infra_match = false,
416};
417#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800418
Jeff Johnson295189b2012-06-20 16:38:30 -0700419static struct cfg80211_ops wlan_hdd_cfg80211_ops;
420
421/* Data rate 100KBPS based on IE Index */
422struct index_data_rate_type
423{
424 v_U8_t beacon_rate_index;
425 v_U16_t supported_rate[4];
426};
427
428/* 11B, 11G Rate table include Basic rate and Extended rate
429 The IDX field is the rate index
430 The HI field is the rate when RSSI is strong or being ignored
431 (in this case we report actual rate)
432 The MID field is the rate when RSSI is moderate
433 (in this case we cap 11b rates at 5.5 and 11g rates at 24)
434 The LO field is the rate when RSSI is low
435 (in this case we don't report rates, actual current rate used)
436 */
437static const struct
438{
439 v_U8_t beacon_rate_index;
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700440 v_U16_t supported_rate[4];
Jeff Johnson295189b2012-06-20 16:38:30 -0700441} supported_data_rate[] =
442{
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700443/* IDX HI HM LM LO (RSSI-based index */
444 {2, { 10, 10, 10, 0}},
445 {4, { 20, 20, 10, 0}},
446 {11, { 55, 20, 10, 0}},
447 {12, { 60, 55, 20, 0}},
448 {18, { 90, 55, 20, 0}},
449 {22, {110, 55, 20, 0}},
450 {24, {120, 90, 60, 0}},
451 {36, {180, 120, 60, 0}},
452 {44, {220, 180, 60, 0}},
453 {48, {240, 180, 90, 0}},
454 {66, {330, 180, 90, 0}},
455 {72, {360, 240, 90, 0}},
456 {96, {480, 240, 120, 0}},
457 {108, {540, 240, 120, 0}}
Jeff Johnson295189b2012-06-20 16:38:30 -0700458};
459
460/* MCS Based rate table */
461static struct index_data_rate_type supported_mcs_rate[] =
462{
463/* MCS L20 L40 S20 S40 */
464 {0, {65, 135, 72, 150}},
465 {1, {130, 270, 144, 300}},
466 {2, {195, 405, 217, 450}},
467 {3, {260, 540, 289, 600}},
468 {4, {390, 810, 433, 900}},
469 {5, {520, 1080, 578, 1200}},
470 {6, {585, 1215, 650, 1350}},
471 {7, {650, 1350, 722, 1500}}
472};
473
Leo Chang6f8870f2013-03-26 18:11:36 -0700474#ifdef WLAN_FEATURE_11AC
475
476#define DATA_RATE_11AC_MCS_MASK 0x0F
477
478struct index_vht_data_rate_type
479{
480 v_U8_t beacon_rate_index;
481 v_U16_t supported_rate[2];
482};
483
484typedef enum
485{
486 DATA_RATE_11AC_MAX_MCS_7,
487 DATA_RATE_11AC_MAX_MCS_8,
488 DATA_RATE_11AC_MAX_MCS_9,
489 DATA_RATE_11AC_MAX_MCS_NA
490} eDataRate11ACMaxMcs;
491
492/* MCS Based VHT rate table */
493static struct index_vht_data_rate_type supported_vht_mcs_rate[] =
494{
495/* MCS L80 S80 */
496 {0, {293, 325}},
497 {1, {585, 650}},
498 {2, {878, 975}},
499 {3, {1170, 1300}},
500 {4, {1755, 1950}},
501 {5, {2340, 2600}},
502 {6, {2633, 2925}},
503 {7, {2925, 3250}},
504 {8, {3510, 3900}},
505 {9, {3900, 4333}}
506};
507#endif /* WLAN_FEATURE_11AC */
508
Jeff Johnson295189b2012-06-20 16:38:30 -0700509extern struct net_device_ops net_ops_struct;
510
511/*
512 * FUNCTION: wlan_hdd_cfg80211_init
513 * This function is called by hdd_wlan_startup()
514 * during initialization.
515 * This function is used to initialize and register wiphy structure.
516 */
517struct wiphy *wlan_hdd_cfg80211_init(int priv_size)
518{
519 struct wiphy *wiphy;
520 ENTER();
521
522 /*
523 * Create wiphy device
524 */
525 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
526
527 if (!wiphy)
528 {
529 /* Print error and jump into err label and free the memory */
530 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__);
531 return NULL;
532 }
533
534 return wiphy;
535}
536
537/*
538 * FUNCTION: wlan_hdd_cfg80211_update_band
539 * This function is called from the supplicant through a
540 * private ioctl to change the band value
541 */
542int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
543{
Jeff Johnsone7245742012-09-05 17:12:55 -0700544 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700545 switch(eBand)
546 {
547 case eCSR_BAND_24:
548 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
549 wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
550 break;
551 case eCSR_BAND_5G:
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700552 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700553 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
554 break;
555 case eCSR_BAND_ALL:
556 default:
557 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
558 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
559 }
560 return 0;
561}
562/*
563 * FUNCTION: wlan_hdd_cfg80211_init
564 * This function is called by hdd_wlan_startup()
565 * during initialization.
566 * This function is used to initialize and register wiphy structure.
567 */
568int wlan_hdd_cfg80211_register(struct device *dev,
569 struct wiphy *wiphy,
570 hdd_config_t *pCfg
571 )
572{
Jeff Johnsone7245742012-09-05 17:12:55 -0700573 ENTER();
574
Jeff Johnson295189b2012-06-20 16:38:30 -0700575 /* Now bind the underlying wlan device with wiphy */
576 set_wiphy_dev(wiphy, dev);
577
578 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
579
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700580 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700581
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700582#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700583 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
584 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
585 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
Jeff Johnsone7245742012-09-05 17:12:55 -0700586 | WIPHY_FLAG_OFFCHAN_TX;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700587#endif
Srinivas Girigowda640728a2013-03-28 12:21:54 -0700588#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
589 if (pCfg->isFastTransitionEnabled
James Zmuda77fb5ae2013-01-29 08:00:17 -0800590#ifdef FEATURE_WLAN_LFR
Srinivas Girigowda640728a2013-03-28 12:21:54 -0700591 || pCfg->isFastRoamIniFeatureEnabled
592#endif
593#ifdef FEATURE_WLAN_CCX
594 || pCfg->isCcxIniFeatureEnabled
595#endif
596 )
597 {
598 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
599 }
James Zmuda77fb5ae2013-01-29 08:00:17 -0800600#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800601#ifdef FEATURE_WLAN_TDLS
602 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
603 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
604#endif
605
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700606 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
607 driver can still register regulatory callback and
608 it will get CRDA setting in wiphy->band[], but
609 driver need to determine what to do with both
610 regulatory settings */
611 wiphy->reg_notifier = wlan_hdd_crda_reg_notifier;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700612
Jeff Johnson295189b2012-06-20 16:38:30 -0700613 wiphy->max_scan_ssids = MAX_SCAN_SSID;
614
615 wiphy->max_scan_ie_len = 200 ; //TODO: define a macro
616
617 /* Supports STATION & AD-HOC modes right now */
618 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
619 | BIT(NL80211_IFTYPE_ADHOC)
Jeff Johnson295189b2012-06-20 16:38:30 -0700620 | BIT(NL80211_IFTYPE_P2P_CLIENT)
621 | BIT(NL80211_IFTYPE_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -0700622 | BIT(NL80211_IFTYPE_AP);
623
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800624#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800625 if( pCfg->enableMCC )
626 {
627 /* Currently, supports up to two channels */
628 wlan_hdd_iface_combination.num_different_channels = 2;
629
630 if( !pCfg->allowMCCGODiffBI )
631 wlan_hdd_iface_combination.beacon_int_infra_match = true;
632
633 }
634 wiphy->iface_combinations = &wlan_hdd_iface_combination;
635 wiphy->n_iface_combinations = 1;
636#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800637
Jeff Johnson295189b2012-06-20 16:38:30 -0700638 /* Before registering we need to update the ht capabilitied based
639 * on ini values*/
640 if( !pCfg->ShortGI20MhzEnable )
641 {
642 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
643 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
644 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
645 }
646
647 if( !pCfg->ShortGI40MhzEnable )
648 {
649 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
650 }
651
652 if( !pCfg->nChannelBondingMode5GHz )
653 {
654 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
655 }
656
657 /*Initialize band capability*/
658 switch(pCfg->nBandCapability)
659 {
660 case eCSR_BAND_24:
661 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
662 break;
663 case eCSR_BAND_5G:
Jeff Johnson295189b2012-06-20 16:38:30 -0700664 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700665 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
666 break;
667 case eCSR_BAND_ALL:
668 default:
669 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
670 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
671 }
672 /*Initialise the supported cipher suite details*/
673 wiphy->cipher_suites = hdd_cipher_suites;
674 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
675
676 /*signal strength in mBm (100*dBm) */
677 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
678
679#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -0700680 wiphy->max_remain_on_channel_duration = 1000;
681#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700682
683 /* Register our wiphy dev with cfg80211 */
684 if (0 > wiphy_register(wiphy))
685 {
686 /* print eror */
687 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
688 return -EIO;
689 }
690
691 EXIT();
692 return 0;
693}
694
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700695/* In this function we will try to get default country code from crda.
696 If the gCrdaDefaultCountryCode is configured in ini file,
697 we will try to call user space crda to get the regulatory settings for
698 that country. We will timeout if we can't get it from crda.
699 It's called by hdd_wlan_startup() after wlan_hdd_cfg80211_register.
700*/
701int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg)
702{
703 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
704 if (memcmp(pCfg->crdaDefaultCountryCode,
705 CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) != 0)
706 {
707 init_completion(&pHddCtx->driver_crda_req);
708 regulatory_hint(wiphy, pCfg->crdaDefaultCountryCode);
709 wait_for_completion_interruptible_timeout(&pHddCtx->driver_crda_req,
710 CRDA_WAIT_TIME);
711 }
712 return 0;
713}
714
Jeff Johnson295189b2012-06-20 16:38:30 -0700715/* In this function we will do all post VOS start initialization.
716 In this function we will register for all frame in which supplicant
717 is interested.
718*/
719void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
720{
Jeff Johnson295189b2012-06-20 16:38:30 -0700721 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
722 /* Register for all P2P action, public action etc frames */
723 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
724
Jeff Johnsone7245742012-09-05 17:12:55 -0700725 ENTER();
726
Jeff Johnson295189b2012-06-20 16:38:30 -0700727 /* Right now we are registering these frame when driver is getting
728 initialized. Once we will move to 2.6.37 kernel, in which we have
729 frame register ops, we will move this code as a part of that */
730 /* GAS Initial Request */
731 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
732 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
733
734 /* GAS Initial Response */
735 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
736 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
737
738 /* GAS Comeback Request */
739 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
740 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
741
742 /* GAS Comeback Response */
743 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
744 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
745
746 /* P2P Public Action */
747 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
748 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
749 P2P_PUBLIC_ACTION_FRAME_SIZE );
750
751 /* P2P Action */
752 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
753 (v_U8_t*)P2P_ACTION_FRAME,
754 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -0700755
756#ifdef WLAN_FEATURE_11W
757 /* SA Query Response Action Frame */
758 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
759 (v_U8_t*)SA_QUERY_FRAME_RSP,
760 SA_QUERY_FRAME_RSP_SIZE );
761#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -0700762}
763
764void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
765{
Jeff Johnson295189b2012-06-20 16:38:30 -0700766 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
767 /* Register for all P2P action, public action etc frames */
768 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
769
Jeff Johnsone7245742012-09-05 17:12:55 -0700770 ENTER();
771
Jeff Johnson295189b2012-06-20 16:38:30 -0700772 /* Right now we are registering these frame when driver is getting
773 initialized. Once we will move to 2.6.37 kernel, in which we have
774 frame register ops, we will move this code as a part of that */
775 /* GAS Initial Request */
776
777 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
778 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
779
780 /* GAS Initial Response */
781 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
782 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
783
784 /* GAS Comeback Request */
785 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
786 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
787
788 /* GAS Comeback Response */
789 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
790 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
791
792 /* P2P Public Action */
793 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
794 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
795 P2P_PUBLIC_ACTION_FRAME_SIZE );
796
797 /* P2P Action */
798 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
799 (v_U8_t*)P2P_ACTION_FRAME,
800 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -0700801
802#ifdef WLAN_FEATURE_11W
803 /* SA Query Response Action Frame */
804 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
805 (v_U8_t*)SA_QUERY_FRAME_RSP,
806 SA_QUERY_FRAME_RSP_SIZE );
807#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -0700808}
809
810#ifdef FEATURE_WLAN_WAPI
811void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
812 const u8 *mac_addr, u8 *key , int key_Len)
813{
814 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
815 tCsrRoamSetKey setKey;
816 v_BOOL_t isConnected = TRUE;
817 int status = 0;
818 v_U32_t roamId= 0xFF;
819 tANI_U8 *pKeyPtr = NULL;
820 int n = 0;
821
822 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
823 __func__,pAdapter->device_mode);
824
Gopichand Nakkalae7480202013-02-11 15:24:22 +0530825 vos_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Jeff Johnson295189b2012-06-20 16:38:30 -0700826 setKey.keyId = key_index; // Store Key ID
827 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
828 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
829 setKey.paeRole = 0 ; // the PAE role
830 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
831 {
832 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
833 }
834 else
835 {
836 isConnected = hdd_connIsConnected(pHddStaCtx);
837 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
838 }
839 setKey.keyLength = key_Len;
840 pKeyPtr = setKey.Key;
841 memcpy( pKeyPtr, key, key_Len);
842
843 hddLog(VOS_TRACE_LEVEL_INFO,"\n%s: WAPI KEY LENGTH:0x%04x",
844 __func__, key_Len);
845 for (n = 0 ; n < key_Len; n++)
846 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
847 __func__,n,setKey.Key[n]);
848
849 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
850 if ( isConnected )
851 {
852 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
853 pAdapter->sessionId, &setKey, &roamId );
854 }
855 if ( status != 0 )
856 {
857 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
858 "[%4d] sme_RoamSetKey returned ERROR status= %d",
859 __LINE__, status );
860 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
861 }
862}
863#endif /* FEATURE_WLAN_WAPI*/
864
865#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
866int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
867 beacon_data_t **ppBeacon,
868 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700869#else
870int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
871 beacon_data_t **ppBeacon,
872 struct cfg80211_beacon_data *params,
873 int dtim_period)
874#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700875{
876 int size;
877 beacon_data_t *beacon = NULL;
878 beacon_data_t *old = NULL;
879 int head_len,tail_len;
880
Jeff Johnsone7245742012-09-05 17:12:55 -0700881 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700882 if (params->head && !params->head_len)
883 return -EINVAL;
884
885 old = pAdapter->sessionCtx.ap.beacon;
886
887 if (!params->head && !old)
888 return -EINVAL;
889
890 if (params->tail && !params->tail_len)
891 return -EINVAL;
892
893#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
894 /* Kernel 3.0 is not updating dtim_period for set beacon */
895 if (!params->dtim_period)
896 return -EINVAL;
897#endif
898
899 if(params->head)
900 head_len = params->head_len;
901 else
902 head_len = old->head_len;
903
904 if(params->tail || !old)
905 tail_len = params->tail_len;
906 else
907 tail_len = old->tail_len;
908
909 size = sizeof(beacon_data_t) + head_len + tail_len;
910
911 beacon = kzalloc(size, GFP_KERNEL);
912
913 if( beacon == NULL )
914 return -ENOMEM;
915
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700916#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700917 if(params->dtim_period || !old )
918 beacon->dtim_period = params->dtim_period;
919 else
920 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700921#else
922 if(dtim_period || !old )
923 beacon->dtim_period = dtim_period;
924 else
925 beacon->dtim_period = old->dtim_period;
926#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700927
928 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
929 beacon->tail = beacon->head + head_len;
930 beacon->head_len = head_len;
931 beacon->tail_len = tail_len;
932
933 if(params->head) {
934 memcpy (beacon->head,params->head,beacon->head_len);
935 }
936 else {
937 if(old)
938 memcpy (beacon->head,old->head,beacon->head_len);
939 }
940
941 if(params->tail) {
942 memcpy (beacon->tail,params->tail,beacon->tail_len);
943 }
944 else {
945 if(old)
946 memcpy (beacon->tail,old->tail,beacon->tail_len);
947 }
948
949 *ppBeacon = beacon;
950
951 kfree(old);
952
953 return 0;
954
955}
Jeff Johnson295189b2012-06-20 16:38:30 -0700956
957v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
958{
959 int left = length;
960 v_U8_t *ptr = pIes;
961 v_U8_t elem_id,elem_len;
962
963 while(left >= 2)
964 {
965 elem_id = ptr[0];
966 elem_len = ptr[1];
967 left -= 2;
968 if(elem_len > left)
969 {
970 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700971 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -0700972 eid,elem_len,left);
973 return NULL;
974 }
975 if (elem_id == eid)
976 {
977 return ptr;
978 }
979
980 left -= elem_len;
981 ptr += (elem_len + 2);
982 }
983 return NULL;
984}
985
Jeff Johnson295189b2012-06-20 16:38:30 -0700986/* Check if rate is 11g rate or not */
987static int wlan_hdd_rate_is_11g(u8 rate)
988{
989 u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 104}; /* actual rate * 2 */
990 u8 i;
991 for (i = 0; i < 8; i++)
992 {
993 if(rate == gRateArray[i])
994 return TRUE;
995 }
996 return FALSE;
997}
998
999/* Check for 11g rate and set proper 11g only mode */
1000static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
1001 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
1002{
1003 u8 i, num_rates = pIe[0];
1004
1005 pIe += 1;
1006 for ( i = 0; i < num_rates; i++)
1007 {
1008 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
1009 {
1010 /* If rate set have 11g rate than change the mode to 11G */
1011 *pSapHw_mode = eSAP_DOT11_MODE_11g;
1012 if (pIe[i] & BASIC_RATE_MASK)
1013 {
1014 /* If we have 11g rate as basic rate, it means mode
1015 is 11g only mode.
1016 */
1017 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
1018 *pCheckRatesfor11g = FALSE;
1019 }
1020 }
1021 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
1022 {
1023 *require_ht = TRUE;
1024 }
1025 }
1026 return;
1027}
1028
1029static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
1030{
1031 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1032 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1033 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1034 u8 checkRatesfor11g = TRUE;
1035 u8 require_ht = FALSE;
1036 u8 *pIe=NULL;
1037
1038 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
1039
1040 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
1041 pBeacon->head_len, WLAN_EID_SUPP_RATES);
1042 if (pIe != NULL)
1043 {
1044 pIe += 1;
1045 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1046 &pConfig->SapHw_mode);
1047 }
1048
1049 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1050 WLAN_EID_EXT_SUPP_RATES);
1051 if (pIe != NULL)
1052 {
1053
1054 pIe += 1;
1055 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1056 &pConfig->SapHw_mode);
1057 }
1058
1059 if( pConfig->channel > 14 )
1060 {
1061 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
1062 }
1063
1064 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1065 WLAN_EID_HT_CAPABILITY);
1066
1067 if(pIe)
1068 {
1069 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
1070 if(require_ht)
1071 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
1072 }
1073}
1074
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301075static int wlan_hdd_add_ie(hdd_adapter_t* pHostapdAdapter, v_U8_t *genie,
1076 v_U8_t *total_ielen, v_U8_t *oui, v_U8_t oui_size)
1077{
1078 v_U8_t ielen = 0;
1079 v_U8_t *pIe = NULL;
1080 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1081
1082 pIe = wlan_hdd_get_vendor_oui_ie_ptr(oui, oui_size,
1083 pBeacon->tail, pBeacon->tail_len);
1084
1085 if (pIe)
1086 {
1087 ielen = pIe[1] + 2;
1088 if ((*total_ielen + ielen) <= MAX_GENIE_LEN)
1089 {
1090 vos_mem_copy(&genie[*total_ielen], pIe, ielen);
1091 }
1092 else
1093 {
1094 hddLog( VOS_TRACE_LEVEL_ERROR, "**Ie Length is too big***");
1095 return -EINVAL;
1096 }
1097 *total_ielen += ielen;
1098 }
1099 return 0;
1100}
1101
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001102#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001103static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1104 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001105#else
1106static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1107 struct cfg80211_beacon_data *params)
1108#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001109{
1110 v_U8_t *genie;
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301111 v_U8_t total_ielen = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001112 v_U8_t addIE[1] = {0};
Jeff Johnsone7245742012-09-05 17:12:55 -07001113 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001114
1115 genie = vos_mem_malloc(MAX_GENIE_LEN);
1116
1117 if(genie == NULL) {
1118
1119 return -ENOMEM;
1120 }
1121
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301122 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1123 &total_ielen, WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001124 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301125 ret = -EINVAL;
1126 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001127 }
1128
1129#ifdef WLAN_FEATURE_WFD
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301130 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1131 &total_ielen, WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE))
1132 {
1133 ret = -EINVAL;
1134 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001135 }
1136#endif
1137
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301138 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1139 &total_ielen, P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001140 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301141 ret = -EINVAL;
1142 goto done;
1143 }
1144
1145 if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode)
1146 {
1147 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1148 &total_ielen, SS_OUI_TYPE, SS_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001149 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301150 ret = -EINVAL;
1151 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001152 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001153 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001154
1155 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1156 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1157 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1158 {
1159 hddLog(LOGE,
1160 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001161 ret = -EINVAL;
1162 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001163 }
1164
1165 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1166 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1167 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1168 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1169 ==eHAL_STATUS_FAILURE)
1170 {
1171 hddLog(LOGE,
1172 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001173 ret = -EINVAL;
1174 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001175 }
1176
1177 // Added for ProResp IE
1178 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1179 {
1180 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1181 u8 probe_rsp_ie_len[3] = {0};
1182 u8 counter = 0;
1183 /* Check Probe Resp Length if it is greater then 255 then Store
1184 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1185 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1186 Store More then 255 bytes into One Variable.
1187 */
1188 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1189 {
1190 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1191 {
1192 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1193 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1194 }
1195 else
1196 {
1197 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1198 rem_probe_resp_ie_len = 0;
1199 }
1200 }
1201
1202 rem_probe_resp_ie_len = 0;
1203
1204 if (probe_rsp_ie_len[0] > 0)
1205 {
1206 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1207 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1208 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1209 probe_rsp_ie_len[0], NULL,
1210 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1211 {
1212 hddLog(LOGE,
1213 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001214 ret = -EINVAL;
1215 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001216 }
1217 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1218 }
1219
1220 if (probe_rsp_ie_len[1] > 0)
1221 {
1222 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1223 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1224 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1225 probe_rsp_ie_len[1], NULL,
1226 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1227 {
1228 hddLog(LOGE,
1229 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001230 ret = -EINVAL;
1231 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001232 }
1233 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1234 }
1235
1236 if (probe_rsp_ie_len[2] > 0)
1237 {
1238 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1239 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1240 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1241 probe_rsp_ie_len[2], NULL,
1242 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1243 {
1244 hddLog(LOGE,
1245 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001246 ret = -EINVAL;
1247 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001248 }
1249 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1250 }
1251
1252 if (probe_rsp_ie_len[1] == 0 )
1253 {
1254 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1255 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1256 eANI_BOOLEAN_FALSE) )
1257 {
1258 hddLog(LOGE,
1259 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1260 }
1261 }
1262
1263 if (probe_rsp_ie_len[2] == 0 )
1264 {
1265 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1266 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1267 eANI_BOOLEAN_FALSE) )
1268 {
1269 hddLog(LOGE,
1270 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1271 }
1272 }
1273
1274 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1275 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1276 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1277 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1278 == eHAL_STATUS_FAILURE)
1279 {
1280 hddLog(LOGE,
1281 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001282 ret = -EINVAL;
1283 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001284 }
1285 }
1286 else
1287 {
1288 // Reset WNI_CFG_PROBE_RSP Flags
1289 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1290
1291 hddLog(VOS_TRACE_LEVEL_INFO,
1292 "%s: No Probe Response IE received in set beacon",
1293 __func__);
1294 }
1295
1296 // Added for AssocResp IE
1297 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1298 {
1299 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1300 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1301 params->assocresp_ies_len, NULL,
1302 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1303 {
1304 hddLog(LOGE,
1305 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001306 ret = -EINVAL;
1307 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001308 }
1309
1310 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1311 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1312 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1313 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1314 == eHAL_STATUS_FAILURE)
1315 {
1316 hddLog(LOGE,
1317 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001318 ret = -EINVAL;
1319 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001320 }
1321 }
1322 else
1323 {
1324 hddLog(VOS_TRACE_LEVEL_INFO,
1325 "%s: No Assoc Response IE received in set beacon",
1326 __func__);
1327
1328 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1329 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1330 eANI_BOOLEAN_FALSE) )
1331 {
1332 hddLog(LOGE,
1333 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1334 }
1335 }
1336
Jeff Johnsone7245742012-09-05 17:12:55 -07001337done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001338 vos_mem_free(genie);
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301339 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07001340}
Jeff Johnson295189b2012-06-20 16:38:30 -07001341
1342/*
1343 * FUNCTION: wlan_hdd_validate_operation_channel
1344 * called by wlan_hdd_cfg80211_start_bss() and
1345 * wlan_hdd_cfg80211_set_channel()
1346 * This function validates whether given channel is part of valid
1347 * channel list.
1348 */
1349static VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
1350{
1351
1352 v_U32_t num_ch = 0;
1353 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1354 u32 indx = 0;
1355 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301356 v_U8_t fValidChannel = FALSE, count = 0;
1357 hdd_config_t *hdd_pConfig_ini= (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07001358
1359 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1360
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301361 if ( hdd_pConfig_ini->sapAllowAllChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001362 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301363 /* Validate the channel */
1364 for (count = RF_CHAN_1 ; count <= RF_CHAN_165 ; count++)
Jeff Johnson295189b2012-06-20 16:38:30 -07001365 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301366 if ( channel == rfChannels[count].channelNum )
1367 {
1368 fValidChannel = TRUE;
1369 break;
1370 }
1371 }
1372 if (fValidChannel != TRUE)
1373 {
1374 hddLog(VOS_TRACE_LEVEL_ERROR,
1375 "%s: Invalid Channel [%d]", __func__, channel);
1376 return VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001377 }
1378 }
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301379 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001380 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301381 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1382 valid_ch, &num_ch))
1383 {
1384 hddLog(VOS_TRACE_LEVEL_ERROR,
1385 "%s: failed to get valid channel list", __func__);
1386 return VOS_STATUS_E_FAILURE;
1387 }
1388 for (indx = 0; indx < num_ch; indx++)
1389 {
1390 if (channel == valid_ch[indx])
1391 {
1392 break;
1393 }
1394 }
1395
1396 if (indx >= num_ch)
1397 {
1398 hddLog(VOS_TRACE_LEVEL_ERROR,
1399 "%s: Invalid Channel [%d]", __func__, channel);
1400 return VOS_STATUS_E_FAILURE;
1401 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001402 }
1403 return VOS_STATUS_SUCCESS;
1404
1405}
1406
Viral Modi3a32cc52013-02-08 11:14:52 -08001407/**
1408 * FUNCTION: wlan_hdd_cfg80211_set_channel
1409 * This function is used to set the channel number
1410 */
1411static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
1412 struct ieee80211_channel *chan,
1413 enum nl80211_channel_type channel_type
1414 )
1415{
1416 v_U32_t num_ch = 0;
Jeff Johnson4416a782013-03-25 14:17:50 -07001417 int channel = 0;
Viral Modi3a32cc52013-02-08 11:14:52 -08001418 hdd_adapter_t *pAdapter = NULL;
1419 int freq = chan->center_freq; /* freq is in MHZ */
1420
1421 ENTER();
1422
1423 if( NULL == dev )
1424 {
1425 hddLog(VOS_TRACE_LEVEL_ERROR,
1426 "%s: Called with dev = NULL.\n", __func__);
1427 return -ENODEV;
1428 }
1429 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1430
1431 hddLog(VOS_TRACE_LEVEL_INFO,
1432 "%s: device_mode = %d freq = %d \n",__func__,
1433 pAdapter->device_mode, chan->center_freq);
1434 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1435 {
1436 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1437 return -EAGAIN;
1438 }
1439
1440 /*
1441 * Do freq to chan conversion
1442 * TODO: for 11a
1443 */
1444
1445 channel = ieee80211_frequency_to_channel(freq);
1446
1447 /* Check freq range */
1448 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
1449 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
1450 {
1451 hddLog(VOS_TRACE_LEVEL_ERROR,
1452 "%s: Channel [%d] is outside valid range from %d to %d\n",
1453 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
1454 WNI_CFG_CURRENT_CHANNEL_STAMAX);
1455 return -EINVAL;
1456 }
1457
1458 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1459
Gopichand Nakkala6ab19562013-03-07 13:59:42 +05301460 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode) &&
1461 (WLAN_HDD_P2P_GO != pAdapter->device_mode))
Viral Modi3a32cc52013-02-08 11:14:52 -08001462 {
1463 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
1464 {
1465 hddLog(VOS_TRACE_LEVEL_ERROR,
1466 "%s: Invalid Channel [%d] \n", __func__, channel);
1467 return -EINVAL;
1468 }
1469 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1470 "%s: set channel to [%d] for device mode =%d",
1471 __func__, channel,pAdapter->device_mode);
1472 }
1473 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Viral Modi3a32cc52013-02-08 11:14:52 -08001474 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Viral Modi3a32cc52013-02-08 11:14:52 -08001475 )
1476 {
1477 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
1478 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
1479 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1480
1481 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
1482 {
1483 /* Link is up then return cant set channel*/
1484 hddLog( VOS_TRACE_LEVEL_ERROR,
1485 "%s: IBSS Associated, can't set the channel\n", __func__);
1486 return -EINVAL;
1487 }
1488
1489 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
1490 pHddStaCtx->conn_info.operationChannel = channel;
1491 pRoamProfile->ChannelInfo.ChannelList =
1492 &pHddStaCtx->conn_info.operationChannel;
1493 }
1494 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Viral Modi3a32cc52013-02-08 11:14:52 -08001495 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Viral Modi3a32cc52013-02-08 11:14:52 -08001496 )
1497 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301498 if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
1499 {
1500 if(VOS_STATUS_SUCCESS !=
1501 wlan_hdd_validate_operation_channel(pAdapter,channel))
1502 {
1503 hddLog(VOS_TRACE_LEVEL_ERROR,
1504 "%s: Invalid Channel [%d] \n", __func__, channel);
1505 return -EINVAL;
1506 }
1507 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1508 }
1509 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
Viral Modi3a32cc52013-02-08 11:14:52 -08001510 {
1511 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
1512
1513 /* If auto channel selection is configured as enable/ 1 then ignore
1514 channel set by supplicant
1515 */
1516 if ( cfg_param->apAutoChannelSelection )
1517 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301518 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel =
1519 AUTO_CHANNEL_SELECT;
Viral Modi3a32cc52013-02-08 11:14:52 -08001520 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1521 "%s: set channel to auto channel (0) for device mode =%d",
1522 __func__, pAdapter->device_mode);
1523 }
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301524 else
1525 {
1526 if(VOS_STATUS_SUCCESS !=
1527 wlan_hdd_validate_operation_channel(pAdapter,channel))
1528 {
1529 hddLog(VOS_TRACE_LEVEL_ERROR,
1530 "%s: Invalid Channel [%d] \n", __func__, channel);
1531 return -EINVAL;
1532 }
1533 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1534 }
Viral Modi3a32cc52013-02-08 11:14:52 -08001535 }
1536 }
1537 else
1538 {
1539 hddLog(VOS_TRACE_LEVEL_FATAL,
1540 "%s: Invalid device mode failed to set valid channel", __func__);
1541 return -EINVAL;
1542 }
1543 EXIT();
1544 return 0;
1545}
1546
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301547/*
1548 * FUNCTION: wlan_hdd_select_cbmode
1549 * called by wlan_hdd_cfg80211_start_bss() and
1550 * This function selects the cbmode based on primary channel
1551 */
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001552VOS_STATUS wlan_sap_select_cbmode(void *pAdapter,eSapPhyMode SapHw_mode, v_U8_t channel)
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301553{
1554 tSmeConfigParams smeConfig;
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001555 hdd_context_t *pHddCtx = ( hdd_context_t *) pAdapter;
1556 hdd_config_t *pConfigIni = ((hdd_context_t *)(pAdapter))->cfg_ini;
1557
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301558 if(
1559#ifdef WLAN_FEATURE_11AC
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001560 SapHw_mode != eSAP_DOT11_MODE_11ac &&
1561 SapHw_mode != eSAP_DOT11_MODE_11ac_ONLY &&
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301562#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001563 SapHw_mode != eSAP_DOT11_MODE_11n &&
1564 SapHw_mode != eSAP_DOT11_MODE_11n_ONLY
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301565 )
1566 {
1567 return VOS_STATUS_SUCCESS;
1568 }
1569
1570 if (!pConfigIni->nChannelBondingMode5GHz) {
1571 return VOS_STATUS_SUCCESS;
1572 }
1573
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001574 //channel = pSapConfig->channel;
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301575 vos_mem_zero(&smeConfig, sizeof (tSmeConfigParams));
1576
1577 sme_GetConfigParam(pHddCtx->hHal, &smeConfig);
1578
1579#ifdef WLAN_FEATURE_11AC
1580
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001581 if ( SapHw_mode == eSAP_DOT11_MODE_11ac ||
1582 SapHw_mode == eSAP_DOT11_MODE_11ac_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301583 {
1584 if ( channel== 36 || channel == 52 || channel == 100 ||
1585 channel == 116 || channel == 149 )
1586 {
1587 smeConfig.csrConfig.channelBondingMode5GHz =
1588 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW - 1;
1589 }
1590 else if ( channel == 40 || channel == 56 || channel == 104 ||
1591 channel == 120 || channel == 153 )
1592 {
1593 smeConfig.csrConfig.channelBondingMode5GHz =
1594 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW - 1;
1595 }
1596 else if ( channel == 44 || channel == 60 || channel == 108 ||
1597 channel == 124 || channel == 157 )
1598 {
1599 smeConfig.csrConfig.channelBondingMode5GHz =
1600 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH -1;
1601 }
1602 else if ( channel == 48 || channel == 64 || channel == 112 ||
1603 channel == 128 || channel == 161 )
1604 {
1605 smeConfig.csrConfig.channelBondingMode5GHz =
1606 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH - 1;
1607 }
Shailender Karmuchi84f11f02013-02-12 17:11:45 -08001608 else if ( channel == 165 )
1609 {
1610 smeConfig.csrConfig.channelBondingMode5GHz = 0;
1611 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301612 }
1613#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001614 if ( SapHw_mode == eSAP_DOT11_MODE_11n ||
1615 SapHw_mode == eSAP_DOT11_MODE_11n_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301616 {
1617 if ( channel== 40 || channel == 48 || channel == 56 ||
1618 channel == 64 || channel == 104 || channel == 112 ||
1619 channel == 120 || channel == 128 || channel == 136 ||
1620 channel == 144 || channel == 153 || channel == 161 )
1621 {
1622 smeConfig.csrConfig.channelBondingMode5GHz = 1;
1623 }
1624 else if ( channel== 36 || channel == 44 || channel == 52 ||
1625 channel == 60 || channel == 100 || channel == 108 ||
1626 channel == 116 || channel == 124 || channel == 132 ||
1627 channel == 140 || channel == 149 || channel == 157 )
1628 {
1629 smeConfig.csrConfig.channelBondingMode5GHz = 2;
1630 }
Shailender Karmuchi84f11f02013-02-12 17:11:45 -08001631 else if ( channel == 165 )
1632 {
1633 smeConfig.csrConfig.channelBondingMode5GHz = 0;
1634 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301635 }
1636 pr_info ("cbmode selected=%ld\n",smeConfig.csrConfig.channelBondingMode5GHz);
1637
1638 sme_UpdateConfig (pHddCtx->hHal,&smeConfig);
1639 return VOS_STATUS_SUCCESS;
1640}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001641
Jeff Johnson295189b2012-06-20 16:38:30 -07001642#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1643static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1644 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001645#else
1646static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1647 struct cfg80211_beacon_data *params,
1648 const u8 *ssid, size_t ssid_len,
1649 enum nl80211_hidden_ssid hidden_ssid)
1650#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001651{
1652 tsap_Config_t *pConfig;
1653 beacon_data_t *pBeacon = NULL;
1654 struct ieee80211_mgmt *pMgmt_frame;
1655 v_U8_t *pIe=NULL;
1656 v_U16_t capab_info;
1657 eCsrAuthType RSNAuthType;
1658 eCsrEncryptionType RSNEncryptType;
1659 eCsrEncryptionType mcRSNEncryptType;
1660 int status = VOS_STATUS_SUCCESS;
1661 tpWLAN_SAPEventCB pSapEventCallback;
1662 hdd_hostapd_state_t *pHostapdState;
1663 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1664 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301665 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001666 struct qc_mac_acl_entry *acl_entry = NULL;
1667 v_SINT_t i;
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001668 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001669
1670 ENTER();
1671
1672 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1673
1674 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1675
1676 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1677
1678 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1679
1680 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1681
1682 //channel is already set in the set_channel Call back
1683 //pConfig->channel = pCommitConfig->channel;
1684
1685 /*Protection parameter to enable or disable*/
1686 pConfig->protEnabled =
1687 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1688
1689 pConfig->dtim_period = pBeacon->dtim_period;
1690
1691 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1692 pConfig->dtim_period);
1693
1694
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001695 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001696 {
1697 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001698 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001699 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001700 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001701 tANI_BOOLEAN restartNeeded;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001702 pConfig->ieee80211d = 1;
1703 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1704 sme_setRegInfo(hHal, pConfig->countryCode);
1705 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
Jeff Johnson295189b2012-06-20 16:38:30 -07001706 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001707 else
1708 {
1709 pConfig->ieee80211d = 0;
1710 }
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301711 /*
1712 * If auto channel is configured i.e. channel is 0,
1713 * so skip channel validation.
1714 */
1715 if( AUTO_CHANNEL_SELECT != pConfig->channel )
1716 {
1717 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1718 {
1719 hddLog(VOS_TRACE_LEVEL_ERROR,
1720 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1721 return -EINVAL;
1722 }
1723 }
1724 else
1725 {
1726 if(1 != pHddCtx->is_dynamic_channel_range_set)
1727 {
1728 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
1729 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
1730 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
1731 }
1732 pHddCtx->is_dynamic_channel_range_set = 0;
1733 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001734 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001735 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001736 {
1737 pConfig->ieee80211d = 0;
1738 }
1739 pConfig->authType = eSAP_AUTO_SWITCH;
1740
1741 capab_info = pMgmt_frame->u.beacon.capab_info;
1742
1743 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
1744 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1745
1746 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1747
1748 /*Set wps station to configured*/
1749 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1750
1751 if(pIe)
1752 {
1753 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1754 {
1755 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1756 return -EINVAL;
1757 }
1758 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1759 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001760 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001761 /* Check 15 bit of WPS IE as it contain information for wps state
1762 * WPS state
1763 */
1764 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1765 {
1766 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1767 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1768 {
1769 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1770 }
1771 }
1772 }
1773 else
1774 {
1775 pConfig->wps_state = SAP_WPS_DISABLED;
1776 }
1777 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
1778
1779 pConfig->RSNWPAReqIELength = 0;
1780 pConfig->pRSNWPAReqIE = NULL;
1781 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1782 WLAN_EID_RSN);
1783 if(pIe && pIe[1])
1784 {
1785 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1786 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1787 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1788 /* The actual processing may eventually be more extensive than
1789 * this. Right now, just consume any PMKIDs that are sent in
1790 * by the app.
1791 * */
1792 status = hdd_softap_unpackIE(
1793 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1794 &RSNEncryptType,
1795 &mcRSNEncryptType,
1796 &RSNAuthType,
1797 pConfig->pRSNWPAReqIE[1]+2,
1798 pConfig->pRSNWPAReqIE );
1799
1800 if( VOS_STATUS_SUCCESS == status )
1801 {
1802 /* Now copy over all the security attributes you have
1803 * parsed out
1804 * */
1805 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1806 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1807 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1808 = RSNEncryptType;
1809 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1810 "EncryptionType = %d mcEncryptionType = %d\n"),
1811 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1812 }
1813 }
1814
1815 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1816 pBeacon->tail, pBeacon->tail_len);
1817
1818 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1819 {
1820 if (pConfig->pRSNWPAReqIE)
1821 {
1822 /*Mixed mode WPA/WPA2*/
1823 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1824 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1825 }
1826 else
1827 {
1828 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1829 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1830 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1831 status = hdd_softap_unpackIE(
1832 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1833 &RSNEncryptType,
1834 &mcRSNEncryptType,
1835 &RSNAuthType,
1836 pConfig->pRSNWPAReqIE[1]+2,
1837 pConfig->pRSNWPAReqIE );
1838
1839 if( VOS_STATUS_SUCCESS == status )
1840 {
1841 /* Now copy over all the security attributes you have
1842 * parsed out
1843 * */
1844 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1845 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1846 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1847 = RSNEncryptType;
1848 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1849 "EncryptionType = %d mcEncryptionType = %d\n"),
1850 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1851 }
1852 }
1853 }
1854
Jeff Johnson4416a782013-03-25 14:17:50 -07001855 if (pConfig->RSNWPAReqIELength > sizeof wpaRsnIEdata) {
1856 hddLog( VOS_TRACE_LEVEL_ERROR, "**RSNWPAReqIELength is too large***");
1857 return -EINVAL;
1858 }
1859
Jeff Johnson295189b2012-06-20 16:38:30 -07001860 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1861
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001862#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001863 if (params->ssid != NULL)
1864 {
1865 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1866 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1867 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1868 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1869 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001870#else
1871 if (ssid != NULL)
1872 {
1873 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1874 pConfig->SSIDinfo.ssid.length = ssid_len;
1875 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1876 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1877 }
1878#endif
1879
Jeff Johnson295189b2012-06-20 16:38:30 -07001880 vos_mem_copy(pConfig->self_macaddr.bytes,
1881 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1882
1883 /* default value */
1884 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1885 pConfig->num_accept_mac = 0;
1886 pConfig->num_deny_mac = 0;
1887
1888 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1889 pBeacon->tail, pBeacon->tail_len);
1890
1891 /* pIe for black list is following form:
1892 type : 1 byte
1893 length : 1 byte
1894 OUI : 4 bytes
1895 acl type : 1 byte
1896 no of mac addr in black list: 1 byte
1897 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1898 */
1899 if ((pIe != NULL) && (pIe[1] != 0))
1900 {
1901 pConfig->SapMacaddr_acl = pIe[6];
1902 pConfig->num_deny_mac = pIe[7];
1903 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1904 pIe[6], pIe[7]);
1905 if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
1906 pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
1907 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1908 for (i = 0; i < pConfig->num_deny_mac; i++)
1909 {
1910 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1911 acl_entry++;
1912 }
1913 }
1914 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1915 pBeacon->tail, pBeacon->tail_len);
1916
1917 /* pIe for white list is following form:
1918 type : 1 byte
1919 length : 1 byte
1920 OUI : 4 bytes
1921 acl type : 1 byte
1922 no of mac addr in white list: 1 byte
1923 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1924 */
1925 if ((pIe != NULL) && (pIe[1] != 0))
1926 {
1927 pConfig->SapMacaddr_acl = pIe[6];
1928 pConfig->num_accept_mac = pIe[7];
1929 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
1930 pIe[6], pIe[7]);
1931 if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
1932 pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
1933 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1934 for (i = 0; i < pConfig->num_accept_mac; i++)
1935 {
1936 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1937 acl_entry++;
1938 }
1939 }
1940 wlan_hdd_set_sapHwmode(pHostapdAdapter);
1941
Jeff Johnsone7245742012-09-05 17:12:55 -07001942#ifdef WLAN_FEATURE_11AC
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08001943 /* Overwrite the hostapd setting for HW mode only for 11ac.
1944 * This is valid only if mode is set to 11n in hostapd and either AUTO or 11ac in .ini .
1945 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode) */
1946 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
1947 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
1948 (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
1949 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1950 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07001951 {
1952 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
1953 }
1954#endif
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301955
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001956 if( AUTO_CHANNEL_SELECT != pConfig->channel)
1957 wlan_sap_select_cbmode((WLAN_HDD_GET_CTX(pHostapdAdapter)),pConfig->SapHw_mode,pConfig->channel);
Jeff Johnson295189b2012-06-20 16:38:30 -07001958 // ht_capab is not what the name conveys,this is used for protection bitmap
1959 pConfig->ht_capab =
1960 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
1961
1962 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
1963 {
1964 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
1965 return -EINVAL;
1966 }
1967
1968 //Uapsd Enabled Bit
1969 pConfig->UapsdEnable =
1970 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
1971 //Enable OBSS protection
1972 pConfig->obssProtEnabled =
1973 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
1974
1975 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
1976 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
1977 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
1978 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
1979 (int)pConfig->channel);
1980 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
1981 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
1982 pConfig->authType);
1983 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
1984 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
1985 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
1986 pConfig->protEnabled, pConfig->obssProtEnabled);
1987
1988 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
1989 {
1990 //Bss already started. just return.
1991 //TODO Probably it should update some beacon params.
1992 hddLog( LOGE, "Bss Already started...Ignore the request");
1993 EXIT();
1994 return 0;
1995 }
1996
1997 pConfig->persona = pHostapdAdapter->device_mode;
1998
1999 pSapEventCallback = hdd_hostapd_SAPEventCB;
2000 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
2001 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
2002 {
2003 hddLog(LOGE,FL("SAP Start Bss fail\n"));
2004 return -EINVAL;
2005 }
2006
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002007 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07002008 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
2009
2010 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2011
2012 if (!VOS_IS_STATUS_SUCCESS(status))
2013 {
2014 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2015 ("ERROR: HDD vos wait for single_event failed!!\n"));
2016 VOS_ASSERT(0);
2017 }
2018
2019 //Succesfully started Bss update the state bit.
2020 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
2021
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002022#ifdef WLAN_FEATURE_P2P_DEBUG
2023 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
2024 {
2025 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
2026 {
2027 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
2028 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002029 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002030 }
2031 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
2032 {
2033 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
2034 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002035 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002036 }
2037 }
2038#endif
2039
Jeff Johnson295189b2012-06-20 16:38:30 -07002040 pHostapdState->bCommit = TRUE;
2041 EXIT();
2042
2043 return 0;
2044}
2045
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002046#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002047static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
2048 struct net_device *dev,
2049 struct beacon_parameters *params)
2050{
2051 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2052 int status=VOS_STATUS_SUCCESS;
2053
2054 ENTER();
2055
2056 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
2057
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002058 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2059 {
2060 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2061 "%s:LOGP in Progress. Ignore!!!", __func__);
2062 return -EAGAIN;
2063 }
2064
Jeff Johnson295189b2012-06-20 16:38:30 -07002065 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002066 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002067 )
2068 {
2069 beacon_data_t *old,*new;
2070
2071 old = pAdapter->sessionCtx.ap.beacon;
2072
2073 if (old)
2074 return -EALREADY;
2075
2076 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2077
2078 if(status != VOS_STATUS_SUCCESS)
2079 {
2080 hddLog(VOS_TRACE_LEVEL_FATAL,
2081 "%s:Error!!! Allocating the new beacon\n",__func__);
2082 return -EINVAL;
2083 }
2084
2085 pAdapter->sessionCtx.ap.beacon = new;
2086
2087 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2088 }
2089
2090 EXIT();
2091 return status;
2092}
2093
2094static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
2095 struct net_device *dev,
2096 struct beacon_parameters *params)
2097{
2098 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2099 int status=VOS_STATUS_SUCCESS;
2100
2101 ENTER();
2102
2103 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2104 __func__,pAdapter->device_mode);
2105
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002106 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2107 {
2108 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2109 "%s:LOGP in Progress. Ignore!!!", __func__);
2110 return -EAGAIN;
2111 }
2112
Jeff Johnson295189b2012-06-20 16:38:30 -07002113 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002114 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002115 )
2116 {
2117 beacon_data_t *old,*new;
2118
2119 old = pAdapter->sessionCtx.ap.beacon;
2120
2121 if (!old)
2122 return -ENOENT;
2123
2124 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2125
2126 if(status != VOS_STATUS_SUCCESS) {
2127 hddLog(VOS_TRACE_LEVEL_FATAL,
2128 "%s: Error!!! Allocating the new beacon\n",__func__);
2129 return -EINVAL;
2130 }
2131
2132 pAdapter->sessionCtx.ap.beacon = new;
2133
2134 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2135 }
2136
2137 EXIT();
2138 return status;
2139}
2140
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002141#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
2142
2143#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002144static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
2145 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002146#else
2147static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
2148 struct net_device *dev)
2149#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002150{
2151 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07002152 hdd_context_t *pHddCtx = NULL;
2153 hdd_scaninfo_t *pScanInfo = NULL;
2154 hdd_adapter_t *staAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002155 VOS_STATUS status = 0;
2156
2157 ENTER();
2158
2159 if (NULL == pAdapter)
2160 {
2161 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002162 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002163 return -ENODEV;
2164 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002165
Jeff Johnson4416a782013-03-25 14:17:50 -07002166 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002167 if (NULL == pHddCtx)
2168 {
2169 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002170 "%s: HDD context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002171 return -ENODEV;
2172 }
Jeff Johnson4416a782013-03-25 14:17:50 -07002173 if (pHddCtx->isLogpInProgress)
2174 {
2175 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2176 "%s:LOGP in Progress. Ignore!!!", __func__);
2177 return -EAGAIN;
2178 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002179
2180 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
2181 if (NULL == staAdapter)
2182 {
2183 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
2184 if (NULL == staAdapter)
2185 {
2186 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002187 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002188 return -ENODEV;
2189 }
2190 }
2191
2192 pScanInfo = &pHddCtx->scan_info;
2193
Jeff Johnson4416a782013-03-25 14:17:50 -07002194 if (pHddCtx->isLogpInProgress)
Jeff Johnson295189b2012-06-20 16:38:30 -07002195 {
2196 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2197 return -EAGAIN;
2198 }
2199
2200 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2201
2202 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2203 __func__,pAdapter->device_mode);
2204
Jeff Johnsone7245742012-09-05 17:12:55 -07002205 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
2206 {
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002207 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Jeff Johnsone7245742012-09-05 17:12:55 -07002208 hdd_abort_mac_scan(staAdapter->pHddCtx);
2209 status = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002210 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07002211 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
2212 if (!status)
2213 {
2214 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson902c9832012-12-10 14:28:09 -08002215 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002216 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07002217 VOS_ASSERT(pScanInfo->mScanPending);
2218 return 0;
2219 }
2220 }
2221
Jeff Johnson295189b2012-06-20 16:38:30 -07002222 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002223 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002224 )
2225 {
2226 beacon_data_t *old;
2227
2228 old = pAdapter->sessionCtx.ap.beacon;
2229
2230 if (!old)
2231 return -ENOENT;
2232
Jeff Johnson295189b2012-06-20 16:38:30 -07002233 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002234
2235 mutex_lock(&pHddCtx->sap_lock);
2236 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2237 {
Jeff Johnson4416a782013-03-25 14:17:50 -07002238 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss(pHddCtx->pvosContext) ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07002239 {
2240 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2241
2242 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2243
2244 if (!VOS_IS_STATUS_SUCCESS(status))
2245 {
2246 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2247 ("ERROR: HDD vos wait for single_event failed!!\n"));
2248 VOS_ASSERT(0);
2249 }
2250 }
2251 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2252 }
2253 mutex_unlock(&pHddCtx->sap_lock);
2254
2255 if(status != VOS_STATUS_SUCCESS)
2256 {
2257 hddLog(VOS_TRACE_LEVEL_FATAL,
2258 "%s:Error!!! Stopping the BSS\n",__func__);
2259 return -EINVAL;
2260 }
2261
Jeff Johnson4416a782013-03-25 14:17:50 -07002262 if (ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002263 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
2264 ==eHAL_STATUS_FAILURE)
2265 {
2266 hddLog(LOGE,
2267 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
2268 }
2269
Jeff Johnson4416a782013-03-25 14:17:50 -07002270 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002271 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2272 eANI_BOOLEAN_FALSE) )
2273 {
2274 hddLog(LOGE,
2275 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
2276 }
2277
2278 // Reset WNI_CFG_PROBE_RSP Flags
2279 wlan_hdd_reset_prob_rspies(pAdapter);
2280
2281 pAdapter->sessionCtx.ap.beacon = NULL;
2282 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002283#ifdef WLAN_FEATURE_P2P_DEBUG
2284 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
2285 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
2286 {
2287 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
2288 "GO got removed");
2289 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
2290 }
2291#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002292 }
2293 EXIT();
2294 return status;
2295}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002296
2297#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2298
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302299static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2300 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002301 struct cfg80211_ap_settings *params)
2302{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302303 hdd_adapter_t *pAdapter;
2304 hdd_context_t *pHddCtx;
2305 int status = 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002306
2307 ENTER();
2308
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302309 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002310 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302311 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2312 "%s: Device is Null", __func__);
2313 return -ENODEV;
2314 }
2315
2316 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2317 if (NULL == pAdapter)
2318 {
2319 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2320 "%s: HDD adapter is Null", __func__);
2321 return -ENODEV;
2322 }
2323
2324 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2325 {
2326 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2327 "%s: HDD adapter magic is invalid", __func__);
2328 return -ENODEV;
2329 }
2330
2331 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2332 if (NULL == pHddCtx)
2333 {
2334 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2335 "%s: HDD context is Null", __func__);
2336 return -ENODEV;
2337 }
2338
2339 if (pHddCtx->isLogpInProgress)
2340 {
2341 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2342 "%s: LOGP in Progress. Ignore!!!", __func__);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002343 return -EAGAIN;
2344 }
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302345
2346 if (pHddCtx->isLoadUnloadInProgress)
2347 {
2348 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2349 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
2350 return -EAGAIN;
2351 }
2352
2353 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2354 __func__, pAdapter->device_mode);
2355
2356 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002357 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002358 )
2359 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302360 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002361
2362 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302363
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002364 if (old)
2365 return -EALREADY;
2366
2367 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2368
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302369 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002370 {
2371 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302372 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002373 return -EINVAL;
2374 }
2375 pAdapter->sessionCtx.ap.beacon = new;
Viral Modi3a32cc52013-02-08 11:14:52 -08002376#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2377 wlan_hdd_cfg80211_set_channel(wiphy, dev, params->channel, params->channel_type);
2378#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002379 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2380 params->ssid_len, params->hidden_ssid);
2381 }
2382
2383 EXIT();
2384 return status;
2385}
2386
2387
2388static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
2389 struct net_device *dev,
2390 struct cfg80211_beacon_data *params)
2391{
2392 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2393 int status=VOS_STATUS_SUCCESS;
2394
2395 ENTER();
2396
2397 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2398 __func__, pAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002399 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2400 {
2401 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2402 return -EAGAIN;
2403 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002404
2405 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002406 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002407 )
2408 {
2409 beacon_data_t *old,*new;
2410
2411 old = pAdapter->sessionCtx.ap.beacon;
2412
2413 if (!old)
2414 return -ENOENT;
2415
2416 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2417
2418 if(status != VOS_STATUS_SUCCESS) {
2419 hddLog(VOS_TRACE_LEVEL_FATAL,
2420 "%s: Error!!! Allocating the new beacon\n",__func__);
2421 return -EINVAL;
2422 }
2423
2424 pAdapter->sessionCtx.ap.beacon = new;
2425
2426 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2427 }
2428
2429 EXIT();
2430 return status;
2431}
2432
2433#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2434
Jeff Johnson295189b2012-06-20 16:38:30 -07002435
2436static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2437 struct net_device *dev,
2438 struct bss_parameters *params)
2439{
2440 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2441
2442 ENTER();
2443
2444 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2445 __func__,pAdapter->device_mode);
2446
2447 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002448 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002449 )
2450 {
2451 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2452 * want to update this parameter */
2453 if (-1 != params->ap_isolate)
2454 {
2455 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
2456 }
2457 }
2458
2459 EXIT();
2460 return 0;
2461}
2462
2463/*
2464 * FUNCTION: wlan_hdd_cfg80211_change_iface
2465 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2466 */
2467int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2468 struct net_device *ndev,
2469 enum nl80211_iftype type,
2470 u32 *flags,
2471 struct vif_params *params
2472 )
2473{
2474 struct wireless_dev *wdev;
2475 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2476 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002477 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002478 tCsrRoamProfile *pRoamProfile = NULL;
2479 eCsrRoamBssType LastBSSType;
2480 hdd_config_t *pConfig = pHddCtx->cfg_ini;
2481 eMib_dot11DesiredBssType connectedBssType;
2482 VOS_STATUS status;
2483
2484 ENTER();
2485
2486 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2487 {
2488 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2489 return -EAGAIN;
2490 }
2491
2492 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2493 __func__, pAdapter->device_mode);
2494
2495 wdev = ndev->ieee80211_ptr;
2496
2497#ifdef WLAN_BTAMP_FEATURE
2498 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2499 (NL80211_IFTYPE_ADHOC == type)||
2500 (NL80211_IFTYPE_AP == type)||
2501 (NL80211_IFTYPE_P2P_GO == type))
2502 {
2503 pHddCtx->isAmpAllowed = VOS_FALSE;
2504 // stop AMP traffic
2505 status = WLANBAP_StopAmp();
2506 if(VOS_STATUS_SUCCESS != status )
2507 {
2508 pHddCtx->isAmpAllowed = VOS_TRUE;
2509 hddLog(VOS_TRACE_LEVEL_FATAL,
2510 "%s: Failed to stop AMP", __func__);
2511 return -EINVAL;
2512 }
2513 }
2514#endif //WLAN_BTAMP_FEATURE
2515 /* Reset the current device mode bit mask*/
2516 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2517
2518 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07002519 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002520 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002521 )
2522 {
2523 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2524 pRoamProfile = &pWextState->roamProfile;
2525 LastBSSType = pRoamProfile->BSSType;
2526
2527 switch (type)
2528 {
2529 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002530 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002531 hddLog(VOS_TRACE_LEVEL_INFO,
2532 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2533 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002534#ifdef WLAN_FEATURE_11AC
2535 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2536 {
2537 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2538 }
2539#endif
2540 pRoamProfile->phyMode =
2541 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002542 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002543 //Check for sub-string p2p to confirm its a p2p interface
2544 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002545 {
2546 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2547 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2548 }
2549 else
2550 {
2551 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002552 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002553 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002554 break;
2555 case NL80211_IFTYPE_ADHOC:
2556 hddLog(VOS_TRACE_LEVEL_INFO,
2557 "%s: setting interface Type to ADHOC", __func__);
2558 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2559 pRoamProfile->phyMode =
2560 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
2561 wdev->iftype = type;
2562 break;
2563
2564 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002565 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002566 {
2567 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2568 "%s: setting interface Type to %s", __func__,
2569 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2570
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002571 //Cancel any remain on channel for GO mode
2572 if (NL80211_IFTYPE_P2P_GO == type)
2573 {
2574 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2575 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002576 if (NL80211_IFTYPE_AP == type)
2577 {
2578 /* As Loading WLAN Driver one interface being created for p2p device
2579 * address. This will take one HW STA and the max number of clients
2580 * that can connect to softAP will be reduced by one. so while changing
2581 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2582 * interface as it is not required in SoftAP mode.
2583 */
2584
2585 // Get P2P Adapter
2586 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2587
2588 if (pP2pAdapter)
2589 {
2590 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2591 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2592 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2593 }
2594 }
2595
Jeff Johnson295189b2012-06-20 16:38:30 -07002596 //De-init the adapter.
2597 hdd_stop_adapter( pHddCtx, pAdapter );
2598 hdd_deinit_adapter( pHddCtx, pAdapter );
2599 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
Jeff Johnson295189b2012-06-20 16:38:30 -07002600 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2601 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002602
2603 //Disable BMPS and IMPS if enabled
2604 //before starting Go
2605 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2606 {
2607 if(VOS_STATUS_E_FAILURE ==
2608 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2609 {
2610 //Fail to Exit BMPS
2611 VOS_ASSERT(0);
2612 }
2613 }
2614
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002615 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2616 (pConfig->apRandomBssidEnabled))
2617 {
2618 /* To meet Android requirements create a randomized
2619 MAC address of the form 02:1A:11:Fx:xx:xx */
2620 get_random_bytes(&ndev->dev_addr[3], 3);
2621 ndev->dev_addr[0] = 0x02;
2622 ndev->dev_addr[1] = 0x1A;
2623 ndev->dev_addr[2] = 0x11;
2624 ndev->dev_addr[3] |= 0xF0;
2625 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2626 VOS_MAC_ADDR_SIZE);
2627 pr_info("wlan: Generated HotSpot BSSID "
2628 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2629 ndev->dev_addr[0],
2630 ndev->dev_addr[1],
2631 ndev->dev_addr[2],
2632 ndev->dev_addr[3],
2633 ndev->dev_addr[4],
2634 ndev->dev_addr[5]);
2635 }
2636
Jeff Johnson295189b2012-06-20 16:38:30 -07002637 hdd_set_ap_ops( pAdapter->dev );
2638
2639 status = hdd_init_ap_mode(pAdapter);
2640 if(status != VOS_STATUS_SUCCESS)
2641 {
2642 hddLog(VOS_TRACE_LEVEL_FATAL,
2643 "%s: Error initializing the ap mode", __func__);
2644 return -EINVAL;
2645 }
2646 hdd_set_conparam(1);
2647
Jeff Johnson295189b2012-06-20 16:38:30 -07002648 /*interface type changed update in wiphy structure*/
2649 if(wdev)
2650 {
2651 wdev->iftype = type;
2652 pHddCtx->change_iface = type;
2653 }
2654 else
2655 {
2656 hddLog(VOS_TRACE_LEVEL_ERROR,
2657 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2658 return -EINVAL;
2659 }
2660 goto done;
2661 }
2662
2663 default:
2664 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2665 __func__);
2666 return -EOPNOTSUPP;
2667 }
2668 }
2669 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002670 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002671 )
2672 {
2673 switch(type)
2674 {
2675 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002676 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002677 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002678 hdd_stop_adapter( pHddCtx, pAdapter );
2679 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002680 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002681 //Check for sub-string p2p to confirm its a p2p interface
2682 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002683 {
2684 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2685 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2686 }
2687 else
2688 {
2689 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002690 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002691 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002692 hdd_set_conparam(0);
2693 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002694 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2695 hdd_set_station_ops( pAdapter->dev );
2696 status = hdd_init_station_mode( pAdapter );
2697 if( VOS_STATUS_SUCCESS != status )
2698 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002699 /* In case of JB, for P2P-GO, only change interface will be called,
2700 * This is the right place to enable back bmps_imps()
2701 */
2702 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002703 goto done;
2704 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002705 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002706 wdev->iftype = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002707 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2708 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07002709 goto done;
2710 default:
2711 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2712 __func__);
2713 return -EOPNOTSUPP;
2714
2715 }
2716
2717 }
2718 else
2719 {
2720 return -EOPNOTSUPP;
2721 }
2722
2723
2724 if(pRoamProfile)
2725 {
2726 if ( LastBSSType != pRoamProfile->BSSType )
2727 {
2728 /*interface type changed update in wiphy structure*/
2729 wdev->iftype = type;
2730
2731 /*the BSS mode changed, We need to issue disconnect
2732 if connected or in IBSS disconnect state*/
2733 if ( hdd_connGetConnectedBssType(
2734 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2735 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2736 {
2737 /*need to issue a disconnect to CSR.*/
2738 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2739 if( eHAL_STATUS_SUCCESS ==
2740 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2741 pAdapter->sessionId,
2742 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2743 {
2744 wait_for_completion_interruptible_timeout(
2745 &pAdapter->disconnect_comp_var,
2746 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2747 }
2748 }
2749 }
2750 }
2751
2752done:
2753 /*set bitmask based on updated value*/
2754 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
2755#ifdef WLAN_BTAMP_FEATURE
2756 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
2757 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2758 {
2759 //we are ok to do AMP
2760 pHddCtx->isAmpAllowed = VOS_TRUE;
2761 }
2762#endif //WLAN_BTAMP_FEATURE
2763 EXIT();
2764 return 0;
2765}
2766
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002767#ifdef FEATURE_WLAN_TDLS
2768static int wlan_hdd_tdls_add_station(struct wiphy *wiphy,
2769 struct net_device *dev, u8 *mac, bool update, tCsrStaParams *StaParams)
2770{
2771 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2772 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2773 VOS_STATUS status;
2774
2775 ENTER();
2776
2777 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
2778 {
2779 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2780 "Invalid arguments");
2781 return -EINVAL;
2782 }
Hoonki Lee27511902013-03-14 18:19:06 -07002783
2784 if ((eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) ||
2785 (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode))
2786 {
2787 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2788 "%s: TDLS mode is disabled OR not enabled in FW."
2789 MAC_ADDRESS_STR " Request declined.",
2790 __func__, MAC_ADDR_ARRAY(mac));
2791 return -ENOTSUPP;
2792 }
2793
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002794 if (pHddCtx->isLogpInProgress)
2795 {
2796 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2797 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07002798 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002799 return -EBUSY;
2800 }
2801
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002802 /* when self is on-going, we dont' want to change link_status */
2803 if ((0 == update) && wlan_hdd_tdls_is_peer_progress(pAdapter, mac))
2804 {
2805 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2806 "%s: " MAC_ADDRESS_STR
2807 " TDLS setup is ongoing. Request declined.",
2808 __func__, MAC_ADDR_ARRAY(mac));
2809 return -EPERM;
2810 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002811 /* when self is not on-ongoing, we don't want to allow change_station */
2812 if ((1 == update) && !wlan_hdd_tdls_is_peer_progress(pAdapter, mac))
2813 {
2814 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2815 "%s: " MAC_ADDRESS_STR
2816 " TDLS is not connecting. change station declined.",
2817 __func__, MAC_ADDR_ARRAY(mac));
2818 return -EPERM;
2819 }
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002820
2821 /* when others are on-going, we want to change link_status to idle */
2822 if (wlan_hdd_tdls_is_progress(pAdapter, mac, TRUE))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002823 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002824 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2825 "%s: " MAC_ADDRESS_STR
2826 " TDLS setup is ongoing. Request declined.",
2827 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002828 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002829 }
2830
2831 /* first to check if we reached to maximum supported TDLS peer.
2832 TODO: for now, return -EPERM looks working fine,
2833 but need to check if any other errno fit into this category.*/
2834 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
2835 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002836 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2837 "%s: " MAC_ADDRESS_STR
2838 " TDLS Max peer already connected. Request declined.",
2839 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002840 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002841 }
2842 else
2843 {
2844 hddTdlsPeer_t *pTdlsPeer;
2845 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002846 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002847 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002848 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2849 "%s: " MAC_ADDRESS_STR " already connected. Request declined.",
2850 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002851 return -EPERM;
2852 }
2853 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002854 if (0 == update)
2855 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_CONNECTING);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002856
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002857 if (NULL != StaParams)
2858 {
2859 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2860 "%s: TDLS Peer Parameters.", __func__);
2861 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2862 "ht_capa->cap_info: %0x", StaParams->HTCap.capInfo);
2863 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2864 "ht_capa->extended_capabilities: %0x",
2865 StaParams->HTCap.extendedHtCapInfo);
2866 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2867 "params->capability: %0x",StaParams->capability);
2868 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2869 "params->ext_capab_len: %0x",StaParams->extn_capability);
2870 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2871 "rxMcsMap %x rxHighest %x txMcsMap %x txHighest %x",
2872 StaParams->VHTCap.suppMcs.rxMcsMap, StaParams->VHTCap.suppMcs.rxHighest,
2873 StaParams->VHTCap.suppMcs.txMcsMap, StaParams->VHTCap.suppMcs.txHighest);
2874 {
2875 int i = 0;
2876 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "Supported rates:");
2877 for (i = 0; i < sizeof(StaParams->supported_rates); i++)
2878 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2879 "[%d]: %x ", i, StaParams->supported_rates[i]);
2880 }
2881 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002882
2883 INIT_COMPLETION(pAdapter->tdls_add_station_comp);
2884
2885 if (!update)
2886 {
2887 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
2888 pAdapter->sessionId, mac);
2889 }
2890 else
2891 {
2892 status = sme_ChangeTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
2893 pAdapter->sessionId, mac, StaParams);
2894 }
2895
2896 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_add_station_comp,
2897 msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
2898
2899 if (!status)
2900 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002901 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002902 "%s: timeout waiting for tdls add station indication",
2903 __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002904 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002905 }
2906 if ( eHAL_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus)
2907 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002908 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002909 "%s: Add Station is unsucessful", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002910 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002911 }
2912
2913 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07002914
2915error:
2916 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
2917 return -EPERM;
2918
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002919}
2920#endif
2921
Jeff Johnson295189b2012-06-20 16:38:30 -07002922static int wlan_hdd_change_station(struct wiphy *wiphy,
2923 struct net_device *dev,
2924 u8 *mac,
2925 struct station_parameters *params)
2926{
2927 VOS_STATUS status = VOS_STATUS_SUCCESS;
2928 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2929 v_MACADDR_t STAMacAddress;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002930#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002931 tCsrStaParams StaParams = {0};
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002932 tANI_U8 isBufSta = 0;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002933#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07002934 ENTER();
2935
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002936 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2937 {
2938 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2939 "%s:LOGP in Progress. Ignore!!!", __func__);
2940 return -EAGAIN;
2941 }
2942
Jeff Johnson295189b2012-06-20 16:38:30 -07002943 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
2944
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002945 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2946 || (pAdapter->device_mode == WLAN_HDD_P2P_GO))
Jeff Johnson295189b2012-06-20 16:38:30 -07002947 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002948 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
Jeff Johnson295189b2012-06-20 16:38:30 -07002949 {
2950 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
2951 WLANTL_STA_AUTHENTICATED);
2952
2953 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002954 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002955 return -EINVAL;
2956 }
2957 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002958#ifdef FEATURE_WLAN_TDLS
Hoonki Leea6d49be2013-04-05 09:43:25 -07002959 else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2960 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) {
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002961 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
2962 StaParams.capability = params->capability;
2963 StaParams.uapsd_queues = params->uapsd_queues;
2964 StaParams.max_sp = params->max_sp;
2965
2966 if (0 != params->ext_capab_len)
2967 vos_mem_copy(StaParams.extn_capability, params->ext_capab,
2968 sizeof(StaParams.extn_capability));
2969
2970 if (NULL != params->ht_capa)
2971 vos_mem_copy(&StaParams.HTCap, params->ht_capa, sizeof(tSirHTCap));
2972
2973 StaParams.supported_rates_len = params->supported_rates_len;
2974
2975 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
2976 * The supported_rates array , for all the structures propogating till Add Sta
2977 * to the firmware has to be modified , if the supplicant (ieee80211) is
2978 * modified to send more rates.
2979 */
2980
2981 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
2982 */
2983 if (StaParams.supported_rates_len > SIR_MAC_MAX_SUPP_RATES)
2984 StaParams.supported_rates_len = SIR_MAC_MAX_SUPP_RATES;
2985
2986 if (0 != StaParams.supported_rates_len) {
2987 int i = 0;
2988 vos_mem_copy(StaParams.supported_rates, params->supported_rates,
2989 StaParams.supported_rates_len);
2990 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2991 "Supported Rates with Length %d", StaParams.supported_rates_len);
2992 for (i=0; i < StaParams.supported_rates_len; i++)
2993 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2994 "[%d]: %0x", i, StaParams.supported_rates[i]);
2995 }
2996
2997 if (NULL != params->vht_capa)
2998 vos_mem_copy(&StaParams.VHTCap, params->vht_capa, sizeof(tSirVHTCap));
2999
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003000 if (0 != params->ext_capab_len ) {
3001 /*Define A Macro : TODO Sunil*/
3002 if ((1<<4) & StaParams.extn_capability[3]) {
3003 isBufSta = 1;
3004 }
3005 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003006 //status = wlan_hdd_tdls_set_peer_caps( mac, params->uapsd_queues,
3007 // params->max_sp, isBufSta);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003008 //if (VOS_STATUS_SUCCESS != status) {
3009 // VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3010 // "%s: wlan_hdd_tdls_set_peer_caps failed!", __func__);
3011 // return -EINVAL;
3012 //}
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003013 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 1, &StaParams);
3014
3015 if (VOS_STATUS_SUCCESS != status) {
3016 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3017 "%s: sme_ChangeTdlsPeerSta failed!", __func__);
3018 return -EINVAL;
3019 }
3020 }
3021 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003022#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003023
Jeff Johnsone7245742012-09-05 17:12:55 -07003024 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003025 return status;
3026}
3027
3028/*
3029 * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
3030 * This function is used to get peer station index in IBSS mode
3031 */
3032static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
3033{
3034 u8 idx = 0;
3035 u8 temp[VOS_MAC_ADDR_SIZE] = {0};
3036 ENTER();
3037 memset(temp, 0, VOS_MAC_ADDR_SIZE);
3038 for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
3039 {
3040 if ( (0 !=
3041 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
3042 && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
3043 temp, VOS_MAC_ADDR_SIZE)
3044 )
3045 {
3046 return idx;
3047 }
3048 }
3049 return idx;
3050}
3051
3052
3053/*
3054 * FUNCTION: wlan_hdd_cfg80211_add_key
3055 * This function is used to initialize the key information
3056 */
3057#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003058static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003059 struct net_device *ndev,
3060 u8 key_index, bool pairwise,
3061 const u8 *mac_addr,
3062 struct key_params *params
3063 )
3064#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003065static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003066 struct net_device *ndev,
3067 u8 key_index, const u8 *mac_addr,
3068 struct key_params *params
3069 )
3070#endif
3071{
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003072 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003073 tCsrRoamSetKey setKey;
3074 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3075 int status = 0;
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003076 v_U32_t roamId= 0xFF;
3077 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003078 hdd_hostapd_state_t *pHostapdState;
3079 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003080 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07003081
3082 ENTER();
3083
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003084 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3085 {
3086 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3087 "%s:LOGP in Progress. Ignore!!!", __func__);
3088 return -EAGAIN;
3089 }
3090
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003091 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
3092 __func__, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003093
3094 if (CSR_MAX_NUM_KEY <= key_index)
3095 {
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003096 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003097 key_index);
3098
3099 return -EINVAL;
3100 }
3101
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003102 if (CSR_MAX_KEY_LEN < params->key_len)
3103 {
3104 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key length %d", __func__,
3105 params->key_len);
3106
3107 return -EINVAL;
3108 }
3109
3110 hddLog(VOS_TRACE_LEVEL_INFO,
3111 "%s: called with key index = %d & key length %d",
3112 __func__, key_index, params->key_len);
Jeff Johnson295189b2012-06-20 16:38:30 -07003113
3114 /*extract key idx, key len and key*/
3115 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3116 setKey.keyId = key_index;
3117 setKey.keyLength = params->key_len;
3118 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
3119
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003120 switch (params->cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07003121 {
3122 case WLAN_CIPHER_SUITE_WEP40:
3123 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
3124 break;
3125
3126 case WLAN_CIPHER_SUITE_WEP104:
3127 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
3128 break;
3129
3130 case WLAN_CIPHER_SUITE_TKIP:
3131 {
3132 u8 *pKey = &setKey.Key[0];
3133 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
3134
3135 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
3136
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003137 /*Supplicant sends the 32bytes key in this order
Jeff Johnson295189b2012-06-20 16:38:30 -07003138
3139 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003140 | Tk1 |TX-MIC | RX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003141 |--------------|----------|----------|
3142 <---16bytes---><--8bytes--><--8bytes-->
3143
3144 */
3145 /*Sme expects the 32 bytes key to be in the below order
3146
3147 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003148 | Tk1 |RX-MIC | TX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003149 |--------------|----------|----------|
3150 <---16bytes---><--8bytes--><--8bytes-->
3151 */
3152 /* Copy the Temporal Key 1 (TK1) */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003153 vos_mem_copy(pKey, params->key, 16);
Jeff Johnson295189b2012-06-20 16:38:30 -07003154
3155 /*Copy the rx mic first*/
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003156 vos_mem_copy(&pKey[16], &params->key[24], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003157
3158 /*Copy the tx mic */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003159 vos_mem_copy(&pKey[24], &params->key[16], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003160
3161
3162 break;
3163 }
3164
3165 case WLAN_CIPHER_SUITE_CCMP:
3166 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
3167 break;
3168
3169#ifdef FEATURE_WLAN_WAPI
3170 case WLAN_CIPHER_SUITE_SMS4:
3171 {
3172 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3173 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
3174 params->key, params->key_len);
3175 return 0;
3176 }
3177#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003178
Jeff Johnson295189b2012-06-20 16:38:30 -07003179#ifdef FEATURE_WLAN_CCX
3180 case WLAN_CIPHER_SUITE_KRK:
3181 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
3182 break;
3183#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003184
3185#ifdef WLAN_FEATURE_11W
3186 case WLAN_CIPHER_SUITE_AES_CMAC:
3187 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
Chet Lanctot3b5158a2013-03-31 16:45:21 -07003188 break;
Chet Lanctot186b5732013-03-18 10:26:30 -07003189#endif
3190
Jeff Johnson295189b2012-06-20 16:38:30 -07003191 default:
3192 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
3193 __func__, params->cipher);
3194 return -EOPNOTSUPP;
3195 }
3196
3197 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
3198 __func__, setKey.encType);
3199
3200
3201
3202 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003203 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07003204 )
3205 {
3206
3207
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003208 if (
Jeff Johnson295189b2012-06-20 16:38:30 -07003209#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3210 (!pairwise)
3211#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003212 (!mac_addr || is_broadcast_ether_addr(mac_addr))
Jeff Johnson295189b2012-06-20 16:38:30 -07003213#endif
3214 )
3215 {
3216 /* set group key*/
3217 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson1250df42012-12-10 14:31:52 -08003218 "%s- %d: setting Broadcast key",
Jeff Johnson295189b2012-06-20 16:38:30 -07003219 __func__, __LINE__);
3220 setKey.keyDirection = eSIR_RX_ONLY;
3221 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3222 }
3223 else
3224 {
3225 /* set pairwise key*/
3226 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3227 "%s- %d: setting pairwise key",
3228 __func__, __LINE__);
3229 setKey.keyDirection = eSIR_TX_RX;
3230 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3231 }
3232
3233 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003234 if( pHostapdState->bssState == BSS_START )
3235 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003236 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3237
3238 if ( status != eHAL_STATUS_SUCCESS )
3239 {
3240 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3241 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3242 __LINE__, status );
3243 }
3244 }
3245
3246 /* Saving WEP keys */
3247 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
3248 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
3249 {
3250 //Save the wep key in ap context. Issue setkey after the BSS is started.
3251 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3252 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
3253 }
3254 else
3255 {
3256 //Save the key in ap context. Issue setkey after the BSS is started.
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003257 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003258 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
3259 }
3260 }
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003261 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
3262 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) )
Jeff Johnson295189b2012-06-20 16:38:30 -07003263 {
3264 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3265 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3266
3267 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
3268
Venkata Prathyusha Kuntupalliee2ce712013-01-17 14:09:24 -08003269 pWextState->roamProfile.Keys.defaultIndex = key_index;
3270
3271
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003272 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07003273 params->key, params->key_len);
3274
3275 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3276
3277 if (!( ( IW_AUTH_KEY_MGMT_802_1X
3278 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
3279 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3280 )
3281 &&
3282 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3283 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3284 )
3285 )
3286 {
3287 /* in case of static WEP, macaddr/bssid is not coming from nl80211
3288 * interface, copy bssid for pairwise key and group macaddr for
3289 * group key initialization*/
3290
3291 tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
3292
3293 pWextState->roamProfile.negotiatedUCEncryptionType =
3294 pHddStaCtx->conn_info.ucEncryptionType =
3295 ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
3296 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
3297 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
3298
3299
3300 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3301 "%s: Negotiated encryption type %d", __func__,
3302 pWextState->roamProfile.negotiatedUCEncryptionType);
3303
3304 sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
3305 &pWextState->roamProfile, true);
3306 setKey.keyLength = 0;
3307 setKey.keyDirection = eSIR_TX_RX;
3308
3309#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3310 if (pairwise)
3311 {
3312#endif
3313 if (mac_addr)
3314 {
3315 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3316 }
3317 else
3318 {
3319 /* macaddr is NULL, set the peerMac to bssId in case of BSS,
3320 * and peerMacAddress in case of IBSS*/
3321 if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
3322 {
3323 u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
3324 if (HDD_MAX_NUM_IBSS_STA != staidx)
3325 {
3326 vos_mem_copy(setKey.peerMac,
3327 &pHddStaCtx->conn_info.peerMacAddress[staidx],
3328 WNI_CFG_BSSID_LEN);
3329
3330 }
3331 else
3332 {
3333 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
3334 __func__);
3335 return -EOPNOTSUPP;
3336 }
3337 }
3338 else
3339 {
3340 vos_mem_copy(setKey.peerMac,
3341 &pHddStaCtx->conn_info.bssId[0],
3342 WNI_CFG_BSSID_LEN);
3343 }
3344 }
3345#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3346 }
3347 else
3348 {
3349 /* set group key*/
3350 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3351 "%s- %d: setting Group key",
3352 __func__, __LINE__);
3353 setKey.keyDirection = eSIR_RX_ONLY;
3354 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3355 }
3356#endif
3357 }
3358 else if (
3359#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3360 (!pairwise)
3361#else
3362 (!mac_addr || is_broadcast_ether_addr(mac_addr))
3363#endif
3364 )
3365 {
3366 /* set group key*/
3367 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3368 "%s- %d: setting Group key",
3369 __func__, __LINE__);
3370 setKey.keyDirection = eSIR_RX_ONLY;
3371 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3372 }
3373 else
3374 {
3375 /* set pairwise key*/
3376 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3377 "%s- %d: setting pairwise key",
3378 __func__, __LINE__);
3379 setKey.keyDirection = eSIR_TX_RX;
3380 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3381 }
3382
3383 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3384 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3385 __func__, setKey.peerMac[0], setKey.peerMac[1],
3386 setKey.peerMac[2], setKey.peerMac[3],
3387 setKey.peerMac[4], setKey.peerMac[5],
3388 setKey.keyDirection);
3389
3390 vos_status = wlan_hdd_check_ula_done(pAdapter);
3391
3392 if ( vos_status != VOS_STATUS_SUCCESS )
3393 {
3394 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3395 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
3396 __LINE__, vos_status );
3397
3398 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3399
3400 return -EINVAL;
3401
3402 }
3403
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003404#ifdef WLAN_FEATURE_VOWIFI_11R
3405 /* The supplicant may attempt to set the PTK once pre-authentication is done.
3406 Save the key in the UMAC and include it in the ADD BSS request */
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003407 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303408 if( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_WAIT )
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003409 {
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303410 return -EINVAL;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003411 }
3412#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07003413
3414 /* issue set key request to SME*/
3415 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3416 pAdapter->sessionId, &setKey, &roamId );
3417
3418 if ( 0 != status )
3419 {
3420 hddLog(VOS_TRACE_LEVEL_ERROR,
3421 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3422 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3423 return -EINVAL;
3424 }
3425
3426
3427 /* in case of IBSS as there was no information available about WEP keys during
3428 * IBSS join, group key intialized with NULL key, so re-initialize group key
3429 * with correct value*/
3430 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
3431 !( ( IW_AUTH_KEY_MGMT_802_1X
3432 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
3433 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3434 )
3435 &&
3436 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3437 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3438 )
3439 )
3440 {
3441 setKey.keyDirection = eSIR_RX_ONLY;
3442 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3443
3444 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3445 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3446 __func__, setKey.peerMac[0], setKey.peerMac[1],
3447 setKey.peerMac[2], setKey.peerMac[3],
3448 setKey.peerMac[4], setKey.peerMac[5],
3449 setKey.keyDirection);
3450
3451 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3452 pAdapter->sessionId, &setKey, &roamId );
3453
3454 if ( 0 != status )
3455 {
3456 hddLog(VOS_TRACE_LEVEL_ERROR,
3457 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
3458 __func__, status);
3459 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3460 return -EINVAL;
3461 }
3462 }
3463 }
3464
3465 return 0;
3466}
3467
3468/*
3469 * FUNCTION: wlan_hdd_cfg80211_get_key
3470 * This function is used to get the key information
3471 */
3472#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3473static int wlan_hdd_cfg80211_get_key(
3474 struct wiphy *wiphy,
3475 struct net_device *ndev,
3476 u8 key_index, bool pairwise,
3477 const u8 *mac_addr, void *cookie,
3478 void (*callback)(void *cookie, struct key_params*)
3479 )
3480#else
3481static int wlan_hdd_cfg80211_get_key(
3482 struct wiphy *wiphy,
3483 struct net_device *ndev,
3484 u8 key_index, const u8 *mac_addr, void *cookie,
3485 void (*callback)(void *cookie, struct key_params*)
3486 )
3487#endif
3488{
3489 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3490 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3491 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
3492 struct key_params params;
3493
3494 ENTER();
3495
3496 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3497 __func__,pAdapter->device_mode);
3498
3499 memset(&params, 0, sizeof(params));
3500
3501 if (CSR_MAX_NUM_KEY <= key_index)
3502 {
3503 return -EINVAL;
3504 }
3505
3506 switch(pRoamProfile->EncryptionType.encryptionType[0])
3507 {
3508 case eCSR_ENCRYPT_TYPE_NONE:
3509 params.cipher = IW_AUTH_CIPHER_NONE;
3510 break;
3511
3512 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3513 case eCSR_ENCRYPT_TYPE_WEP40:
3514 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3515 break;
3516
3517 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3518 case eCSR_ENCRYPT_TYPE_WEP104:
3519 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3520 break;
3521
3522 case eCSR_ENCRYPT_TYPE_TKIP:
3523 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3524 break;
3525
3526 case eCSR_ENCRYPT_TYPE_AES:
3527 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3528 break;
3529
3530 default:
3531 params.cipher = IW_AUTH_CIPHER_NONE;
3532 break;
3533 }
3534
3535 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3536 params.seq_len = 0;
3537 params.seq = NULL;
3538 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3539 callback(cookie, &params);
3540 return 0;
3541}
3542
3543/*
3544 * FUNCTION: wlan_hdd_cfg80211_del_key
3545 * This function is used to delete the key information
3546 */
3547#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3548static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3549 struct net_device *ndev,
3550 u8 key_index,
3551 bool pairwise,
3552 const u8 *mac_addr
3553 )
3554#else
3555static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3556 struct net_device *ndev,
3557 u8 key_index,
3558 const u8 *mac_addr
3559 )
3560#endif
3561{
3562 int status = 0;
3563
3564 //This code needs to be revisited. There is sme_removeKey API, we should
3565 //plan to use that. After the change to use correct index in setkey,
3566 //it is observed that this is invalidating peer
3567 //key index whenever re-key is done. This is affecting data link.
3568 //It should be ok to ignore del_key.
3569#if 0
3570 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3571 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
3572 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3573 tCsrRoamSetKey setKey;
3574 v_U32_t roamId= 0xFF;
3575
3576 ENTER();
3577
3578 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3579 __func__,pAdapter->device_mode);
3580
3581 if (CSR_MAX_NUM_KEY <= key_index)
3582 {
3583 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3584 key_index);
3585
3586 return -EINVAL;
3587 }
3588
3589 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3590 setKey.keyId = key_index;
3591
3592 if (mac_addr)
3593 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3594 else
3595 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3596
3597 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3598
3599 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003600 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07003601 )
3602 {
3603
3604 hdd_hostapd_state_t *pHostapdState =
3605 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3606 if( pHostapdState->bssState == BSS_START)
3607 {
3608 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3609
3610 if ( status != eHAL_STATUS_SUCCESS )
3611 {
3612 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3613 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3614 __LINE__, status );
3615 }
3616 }
3617 }
3618 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003619 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003620 )
3621 {
3622 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3623
3624 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3625
3626 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3627 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
3628 __func__, setKey.peerMac[0], setKey.peerMac[1],
3629 setKey.peerMac[2], setKey.peerMac[3],
3630 setKey.peerMac[4], setKey.peerMac[5]);
3631 if(pAdapter->sessionCtx.station.conn_info.connState ==
3632 eConnectionState_Associated)
3633 {
3634 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3635 pAdapter->sessionId, &setKey, &roamId );
3636
3637 if ( 0 != status )
3638 {
3639 hddLog(VOS_TRACE_LEVEL_ERROR,
3640 "%s: sme_RoamSetKey failure, returned %d",
3641 __func__, status);
3642 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3643 return -EINVAL;
3644 }
3645 }
3646 }
3647#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003648 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003649 return status;
3650}
3651
3652/*
3653 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3654 * This function is used to set the default tx key index
3655 */
3656#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3657static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3658 struct net_device *ndev,
3659 u8 key_index,
3660 bool unicast, bool multicast)
3661#else
3662static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3663 struct net_device *ndev,
3664 u8 key_index)
3665#endif
3666{
3667 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3668 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3669 int status = 0;
3670 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3671
3672 ENTER();
3673
3674 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3675 __func__,pAdapter->device_mode, key_index);
3676
3677 if (CSR_MAX_NUM_KEY <= key_index)
3678 {
3679 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3680 key_index);
3681
3682 return -EINVAL;
3683 }
3684
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003685 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3686 {
3687 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3688 "%s:LOGP in Progress. Ignore!!!", __func__);
3689 return -EAGAIN;
3690 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003691
3692 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003693 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003694 )
3695 {
3696 if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
3697 (eCSR_ENCRYPT_TYPE_TKIP !=
3698 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3699 (eCSR_ENCRYPT_TYPE_AES !=
3700 pWextState->roamProfile.EncryptionType.encryptionType[0])
3701 )
3702 {
3703 /* if default key index is not same as previous one,
3704 * then update the default key index */
3705
3706 tCsrRoamSetKey setKey;
3707 v_U32_t roamId= 0xFF;
3708 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
3709
3710 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
3711 __func__, key_index);
3712
3713 Keys->defaultIndex = (u8)key_index;
3714 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3715 setKey.keyId = key_index;
3716 setKey.keyLength = Keys->KeyLength[key_index];
3717
3718 vos_mem_copy(&setKey.Key[0],
3719 &Keys->KeyMaterial[key_index][0],
3720 Keys->KeyLength[key_index]);
3721
3722 setKey.keyDirection = eSIR_TX_ONLY;
3723
3724 vos_mem_copy(setKey.peerMac,
3725 &pHddStaCtx->conn_info.bssId[0],
3726 WNI_CFG_BSSID_LEN);
3727
3728 setKey.encType =
3729 pWextState->roamProfile.EncryptionType.encryptionType[0];
3730
3731 /* issue set key request */
3732 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3733 pAdapter->sessionId, &setKey, &roamId );
3734
3735 if ( 0 != status )
3736 {
3737 hddLog(VOS_TRACE_LEVEL_ERROR,
3738 "%s: sme_RoamSetKey failed, returned %d", __func__,
3739 status);
3740 return -EINVAL;
3741 }
3742 }
3743 }
3744
3745 /* In SoftAp mode setting key direction for default mode */
3746 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3747 {
3748 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3749 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3750 (eCSR_ENCRYPT_TYPE_AES !=
3751 pWextState->roamProfile.EncryptionType.encryptionType[0])
3752 )
3753 {
3754 /* Saving key direction for default key index to TX default */
3755 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3756 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3757 }
3758 }
3759
3760 return status;
3761}
3762
Jeff Johnson295189b2012-06-20 16:38:30 -07003763/*
3764 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3765 * This function is used to inform the BSS details to nl80211 interface.
3766 */
3767static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3768 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3769{
3770 struct net_device *dev = pAdapter->dev;
3771 struct wireless_dev *wdev = dev->ieee80211_ptr;
3772 struct wiphy *wiphy = wdev->wiphy;
3773 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3774 int chan_no;
3775 int ie_length;
3776 const char *ie;
3777 unsigned int freq;
3778 struct ieee80211_channel *chan;
3779 int rssi = 0;
3780 struct cfg80211_bss *bss = NULL;
3781
3782 ENTER();
3783
3784 if( NULL == pBssDesc )
3785 {
3786 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3787 return bss;
3788 }
3789
3790 chan_no = pBssDesc->channelId;
3791 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3792 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3793
3794 if( NULL == ie )
3795 {
3796 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3797 return bss;
3798 }
3799
3800#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3801 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3802 {
3803 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3804 }
3805 else
3806 {
3807 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3808 }
3809#else
3810 freq = ieee80211_channel_to_frequency(chan_no);
3811#endif
3812
3813 chan = __ieee80211_get_channel(wiphy, freq);
3814
3815 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3816 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3817 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3818 if (bss == NULL)
3819 {
3820 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3821
3822 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3823 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3824 pBssDesc->capabilityInfo,
3825 pBssDesc->beaconInterval, ie, ie_length,
3826 rssi, GFP_KERNEL ));
3827}
3828 else
3829 {
3830 return bss;
3831 }
3832}
3833
3834
3835
3836/*
3837 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3838 * This function is used to inform the BSS details to nl80211 interface.
3839 */
3840struct cfg80211_bss*
3841wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3842 tSirBssDescription *bss_desc
3843 )
3844{
3845 /*
3846 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3847 already exists in bss data base of cfg80211 for that particular BSS ID.
3848 Using cfg80211_inform_bss_frame to update the bss entry instead of
3849 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3850 now there is no possibility to get the mgmt(probe response) frame from PE,
3851 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3852 cfg80211_inform_bss_frame.
3853 */
3854 struct net_device *dev = pAdapter->dev;
3855 struct wireless_dev *wdev = dev->ieee80211_ptr;
3856 struct wiphy *wiphy = wdev->wiphy;
3857 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003858#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3859 qcom_ie_age *qie_age = NULL;
3860 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3861#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003862 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003863#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003864 const char *ie =
3865 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3866 unsigned int freq;
3867 struct ieee80211_channel *chan;
3868 struct ieee80211_mgmt *mgmt =
3869 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3870 struct cfg80211_bss *bss_status = NULL;
3871 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3872 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003873#ifdef WLAN_OPEN_SOURCE
3874 struct timespec ts;
3875#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003876
3877 ENTER();
3878
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003879 if (!mgmt)
3880 return NULL;
3881
Jeff Johnson295189b2012-06-20 16:38:30 -07003882 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003883
3884#ifdef WLAN_OPEN_SOURCE
3885 /* Android does not want the timestamp from the frame.
3886 Instead it wants a monotonic increasing value */
3887 get_monotonic_boottime(&ts);
3888 mgmt->u.probe_resp.timestamp =
3889 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3890#else
3891 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003892 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3893 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003894
3895#endif
3896
Jeff Johnson295189b2012-06-20 16:38:30 -07003897 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3898 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003899
3900#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3901 /* GPS Requirement: need age ie per entry. Using vendor specific. */
3902 /* Assuming this is the last IE, copy at the end */
3903 ie_length -=sizeof(qcom_ie_age);
3904 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
3905 qie_age->element_id = QCOM_VENDOR_IE_ID;
3906 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
3907 qie_age->oui_1 = QCOM_OUI1;
3908 qie_age->oui_2 = QCOM_OUI2;
3909 qie_age->oui_3 = QCOM_OUI3;
3910 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
3911 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
3912#endif
3913
Jeff Johnson295189b2012-06-20 16:38:30 -07003914 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3915
3916 mgmt->frame_control |=
3917 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3918
3919#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3920 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3921 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3922 {
3923 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3924 }
3925 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3926 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3927
3928 {
3929 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3930 }
3931 else
3932 {
3933 kfree(mgmt);
3934 return NULL;
3935 }
3936#else
3937 freq = ieee80211_channel_to_frequency(chan_no);
3938#endif
3939 chan = __ieee80211_get_channel(wiphy, freq);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08003940 /*when the band is changed on the fly using the GUI, three things are done
3941 * 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)
3942 * as part of the scan abort, message willbe queued to PE and we proceed with flushing and changinh the band.
3943 * pe will stop the scanning further and report back the results what ever it had till now by calling the call back function.
3944 * if the time between update band and scandone call back is sufficent enough the band change reflects in SME, SME validates the channels
3945 * and discards the channels correponding to previous band and calls back with zero bss results.
3946 * 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
3947 * all the channels correponding to previous band.this is due to race condition.but those channels are invalid to the new band and so
3948 * this function __ieee80211_get_channel will return NULL.Each time we report scan result with this pointer null warning kernel trace is printed.
3949 * if the scan results contain large number of APs continuosly kernel warning trace is printed and it will lead to apps watch dog bark.
3950 * So drop the bss and continue to next bss.
3951 */
3952 if(chan == NULL)
3953 {
3954 hddLog(VOS_TRACE_LEVEL_INFO, "%s chan pointer is NULL", __func__);
Chilam Ngc4244af2013-04-01 15:37:32 -07003955 kfree(mgmt);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08003956 return NULL;
3957 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003958 /*To keep the rssi icon of the connected AP in the scan window
3959 *and the rssi icon of the wireless networks in sync
3960 * */
3961 if (( eConnectionState_Associated ==
3962 pAdapter->sessionCtx.station.conn_info.connState ) &&
3963 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3964 pAdapter->sessionCtx.station.conn_info.bssId,
3965 WNI_CFG_BSSID_LEN)))
3966 {
3967 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3968 rssi = (pAdapter->rssi * 100);
3969 }
3970 else
3971 {
3972 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3973 }
3974
3975 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3976 frame_len, rssi, GFP_KERNEL);
3977 kfree(mgmt);
3978 return bss_status;
3979}
3980
3981/*
3982 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3983 * This function is used to update the BSS data base of CFG8011
3984 */
3985struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3986 tCsrRoamInfo *pRoamInfo
3987 )
3988{
3989 tCsrRoamConnectedProfile roamProfile;
3990 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3991 struct cfg80211_bss *bss = NULL;
3992
3993 ENTER();
3994
3995 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
3996 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
3997
3998 if (NULL != roamProfile.pBssDesc)
3999 {
4000 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
4001 &roamProfile);
4002
4003 if (NULL == bss)
4004 {
4005 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
4006 __func__);
4007 }
4008
4009 sme_RoamFreeConnectProfile(hHal, &roamProfile);
4010 }
4011 else
4012 {
4013 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
4014 __func__);
4015 }
4016 return bss;
4017}
4018
4019/*
4020 * FUNCTION: wlan_hdd_cfg80211_update_bss
4021 */
4022static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
4023 hdd_adapter_t *pAdapter
4024 )
4025{
4026 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4027 tCsrScanResultInfo *pScanResult;
4028 eHalStatus status = 0;
4029 tScanResultHandle pResult;
4030 struct cfg80211_bss *bss_status = NULL;
4031
4032 ENTER();
4033
4034 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4035 {
4036 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
4037 return -EAGAIN;
4038 }
4039
4040 /*
4041 * start getting scan results and populate cgf80211 BSS database
4042 */
4043 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
4044
4045 /* no scan results */
4046 if (NULL == pResult)
4047 {
4048 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
4049 return status;
4050 }
4051
4052 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
4053
4054 while (pScanResult)
4055 {
4056 /*
4057 * cfg80211_inform_bss() is not updating ie field of bss entry, if
4058 * entry already exists in bss data base of cfg80211 for that
4059 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
4060 * bss entry instead of cfg80211_inform_bss, But this call expects
4061 * mgmt packet as input. As of now there is no possibility to get
4062 * the mgmt(probe response) frame from PE, converting bss_desc to
4063 * ieee80211_mgmt(probe response) and passing to c
4064 * fg80211_inform_bss_frame.
4065 * */
4066
4067 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
4068 &pScanResult->BssDescriptor);
4069
4070
4071 if (NULL == bss_status)
4072 {
4073 hddLog(VOS_TRACE_LEVEL_INFO,
4074 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
4075 }
4076 else
4077 {
4078 cfg80211_put_bss(bss_status);
4079 }
4080
4081 pScanResult = sme_ScanResultGetNext(hHal, pResult);
4082 }
4083
4084 sme_ScanResultPurge(hHal, pResult);
4085
4086 return 0;
4087}
4088
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004089void
4090hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
4091{
4092 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004093 "%02X:%02X:%02X:%02X:%02X:%02X\n",
4094 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
4095 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004096} /****** end hddPrintMacAddr() ******/
4097
4098void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004099hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004100{
4101 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004102 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
4103 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
4104 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
4105 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004106} /****** end hddPrintPmkId() ******/
4107
4108//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
4109//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
4110
4111//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
4112//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
4113
4114#define dump_bssid(bssid) \
4115 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004116 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
4117 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
4118 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004119 }
4120
4121#define dump_pmkid(pMac, pmkid) \
4122 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004123 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
4124 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
4125 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004126 }
4127
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07004128#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004129/*
4130 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
4131 * This function is used to notify the supplicant of a new PMKSA candidate.
4132 */
4133int wlan_hdd_cfg80211_pmksa_candidate_notify(
4134 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
4135 int index, bool preauth )
4136{
Jeff Johnsone7245742012-09-05 17:12:55 -07004137#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004138 struct net_device *dev = pAdapter->dev;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004139 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004140
4141 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07004142 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004143
4144 if( NULL == pRoamInfo )
4145 {
4146 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
4147 return -EINVAL;
4148 }
4149
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004150 if (eANI_BOOLEAN_TRUE == hdd_is_okc_mode_enabled(pHddCtx))
4151 {
4152 dump_bssid(pRoamInfo->bssid);
4153 cfg80211_pmksa_candidate_notify(dev, index,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004154 pRoamInfo->bssid, preauth, GFP_KERNEL);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004155 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004156#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004157 return 0;
4158}
4159#endif //FEATURE_WLAN_LFR
4160
Jeff Johnson295189b2012-06-20 16:38:30 -07004161/*
4162 * FUNCTION: hdd_cfg80211_scan_done_callback
4163 * scanning callback function, called after finishing scan
4164 *
4165 */
4166static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
4167 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
4168{
4169 struct net_device *dev = (struct net_device *) pContext;
4170 //struct wireless_dev *wdev = dev->ieee80211_ptr;
4171 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004172 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4173 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004174 struct cfg80211_scan_request *req = NULL;
4175 int ret = 0;
4176
4177 ENTER();
4178
4179 hddLog(VOS_TRACE_LEVEL_INFO,
4180 "%s called with halHandle = %p, pContext = %p,"
4181 "scanID = %d, returned status = %d\n",
4182 __func__, halHandle, pContext, (int) scanId, (int) status);
4183
4184 //Block on scan req completion variable. Can't wait forever though.
4185 ret = wait_for_completion_interruptible_timeout(
4186 &pScanInfo->scan_req_completion_event,
4187 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
4188 if (!ret)
4189 {
4190 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004191 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004192 }
4193
4194 if(pScanInfo->mScanPending != VOS_TRUE)
4195 {
4196 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004197 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004198 }
4199
4200 /* Check the scanId */
4201 if (pScanInfo->scanId != scanId)
4202 {
4203 hddLog(VOS_TRACE_LEVEL_INFO,
4204 "%s called with mismatched scanId pScanInfo->scanId = %d "
4205 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
4206 (int) scanId);
4207 }
4208
Jeff Johnson295189b2012-06-20 16:38:30 -07004209 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
4210 pAdapter);
4211
4212 if (0 > ret)
4213 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
4214
4215
4216 /* If any client wait scan result through WEXT
4217 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004218 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07004219 {
4220 /* The other scan request waiting for current scan finish
4221 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004222 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004223 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004224 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004225 }
4226 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004227 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004228 {
4229 struct net_device *dev = pAdapter->dev;
4230 union iwreq_data wrqu;
4231 int we_event;
4232 char *msg;
4233
4234 memset(&wrqu, '\0', sizeof(wrqu));
4235 we_event = SIOCGIWSCAN;
4236 msg = NULL;
4237 wireless_send_event(dev, we_event, &wrqu, msg);
4238 }
4239 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004240 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004241
4242 /* Get the Scan Req */
4243 req = pAdapter->request;
4244
4245 if (!req)
4246 {
4247 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004248 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07004249 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004250 }
4251
4252 /*
4253 * setting up 0, just in case.
4254 */
4255 req->n_ssids = 0;
4256 req->n_channels = 0;
4257 req->ie = 0;
4258
Jeff Johnson295189b2012-06-20 16:38:30 -07004259 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004260 /* Scan is no longer pending */
4261 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004262
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07004263 /*
4264 * cfg80211_scan_done informing NL80211 about completion
4265 * of scanning
4266 */
4267 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004268 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004269
Jeff Johnsone7245742012-09-05 17:12:55 -07004270allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004271 /* release the wake lock at the end of the scan*/
4272 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004273
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004274 /* Acquire wakelock to handle the case where APP's tries to suspend
4275 * immediatly after the driver gets connect request(i.e after scan)
4276 * from supplicant, this result in app's is suspending and not able
4277 * to process the connect request to AP */
4278 hdd_allow_suspend_timeout(100);
4279
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004280#ifdef FEATURE_WLAN_TDLS
4281 wlan_hdd_tdls_scan_done_callback(pAdapter);
4282#endif
4283
Jeff Johnson295189b2012-06-20 16:38:30 -07004284 EXIT();
4285 return 0;
4286}
4287
4288/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004289 * FUNCTION: hdd_isScanAllowed
4290 * Go through each adapter and check if scan allowed
4291 *
4292 */
4293v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
4294{
4295 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4296 hdd_station_ctx_t *pHddStaCtx = NULL;
4297 hdd_adapter_t *pAdapter = NULL;
4298 VOS_STATUS status = 0;
4299 v_U8_t staId = 0;
4300 v_U8_t *staMac = NULL;
4301
4302 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4303
4304 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4305 {
4306 pAdapter = pAdapterNode->pAdapter;
4307
4308 if( pAdapter )
4309 {
4310 hddLog(VOS_TRACE_LEVEL_INFO,
4311 "%s: Adapter with device mode %d exists",
4312 __func__, pAdapter->device_mode);
4313 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4314 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4315 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
4316 {
4317 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4318 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
4319 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
4320 {
4321 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
4322 hddLog(VOS_TRACE_LEVEL_ERROR,
4323 "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the "
4324 "middle of WPS/EAPOL exchange.", __func__,
4325 staMac[0], staMac[1], staMac[2],
4326 staMac[3], staMac[4], staMac[5]);
4327 return VOS_FALSE;
4328 }
4329 }
4330 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
4331 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
4332 {
4333 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
4334 {
4335 if ((pAdapter->aStaInfo[staId].isUsed) &&
4336 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
4337 {
4338 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
4339
4340 hddLog(VOS_TRACE_LEVEL_ERROR,
4341 "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the "
4342 "middle of WPS/EAPOL exchange.", __func__,
4343 staMac[0], staMac[1], staMac[2],
4344 staMac[3], staMac[4], staMac[5]);
4345 return VOS_FALSE;
4346 }
4347 }
4348 }
4349 }
4350 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4351 pAdapterNode = pNext;
4352 }
4353 hddLog(VOS_TRACE_LEVEL_INFO,
4354 "%s: Scan allowed", __func__);
4355 return VOS_TRUE;
4356}
4357
4358/*
Jeff Johnson295189b2012-06-20 16:38:30 -07004359 * FUNCTION: wlan_hdd_cfg80211_scan
4360 * this scan respond to scan trigger and update cfg80211 scan database
4361 * later, scan dump command can be used to recieve scan results
4362 */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08004363int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
4364#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4365 struct net_device *dev,
4366#endif
4367 struct cfg80211_scan_request *request)
4368{
4369#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4370 struct net_device *dev = request->wdev->netdev;
4371#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004372 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4373 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4374 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4375 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
4376 tCsrScanRequest scanRequest;
4377 tANI_U8 *channelList = NULL, i;
4378 v_U32_t scanId = 0;
4379 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004380 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004381 v_U8_t* pP2pIe = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004382
4383 ENTER();
4384
4385 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4386 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004387
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004388 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004389 (eConnectionState_Connecting ==
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004390 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004391 {
4392 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004393 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
4394 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004395 return -EBUSY;
4396 }
4397
Jeff Johnson295189b2012-06-20 16:38:30 -07004398#ifdef WLAN_BTAMP_FEATURE
4399 //Scan not supported when AMP traffic is on.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004400 if (VOS_TRUE == WLANBAP_AmpSessionOn())
Jeff Johnson295189b2012-06-20 16:38:30 -07004401 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004402 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004403 "%s: No scanning when AMP is on", __func__);
4404 return -EOPNOTSUPP;
4405 }
4406#endif
4407 //Scan on any other interface is not supported.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004408 if (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07004409 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004410 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004411 "%s: Not scanning on device_mode = %d",
4412 __func__, pAdapter->device_mode);
4413 return -EOPNOTSUPP;
4414 }
4415
4416 if (TRUE == pScanInfo->mScanPending)
4417 {
4418 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004419 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07004420 }
4421
4422 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4423 {
4424 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4425 "%s:LOGP in Progress. Ignore!!!", __func__);
4426 return -EAGAIN;
4427 }
4428
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07004429 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
4430 {
4431 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4432 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
4433 return -EAGAIN;
4434 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004435 //Don't Allow Scan and return busy if Remain On
4436 //Channel and action frame is pending
4437 //Otherwise Cancel Remain On Channel and allow Scan
4438 //If no action frame pending
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004439 if (0 != wlan_hdd_check_remain_on_channel(pAdapter))
Jeff Johnson32d95a32012-09-10 13:15:23 -07004440 {
4441 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
4442 return -EBUSY;
4443 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004444#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004445 /* if tdls disagree scan right now, return immediately.
4446 tdls will schedule the scan when scan is allowed. (return SUCCESS)
4447 or will reject the scan if any TDLS is in progress. (return -EBUSY)
4448 */
4449 status = wlan_hdd_tdls_scan_callback (pAdapter,
4450 wiphy,
4451#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4452 dev,
Gopichand Nakkalac3c42b92013-03-20 19:42:34 -07004453#endif
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004454 request);
4455 if(status <= 0)
4456 {
4457 hddLog(VOS_TRACE_LEVEL_INFO, "%s: TDLS Pending %d", __func__, status);
4458 return status;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004459 }
4460#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07004461
Jeff Johnson295189b2012-06-20 16:38:30 -07004462 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
4463 {
4464 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08004465 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004466 return -EAGAIN;
4467 }
4468 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
4469 {
4470 hddLog(VOS_TRACE_LEVEL_WARN,
4471 "%s: MAX TM Level Scan not allowed", __func__);
4472 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4473 return -EBUSY;
4474 }
4475 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4476
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004477 /* Check if scan is allowed at this point of time.
4478 */
4479 if (!hdd_isScanAllowed(pHddCtx))
4480 {
4481 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
4482 return -EBUSY;
4483 }
4484
Jeff Johnson295189b2012-06-20 16:38:30 -07004485 vos_mem_zero( &scanRequest, sizeof(scanRequest));
4486
4487 if (NULL != request)
4488 {
4489 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
4490 (int)request->n_ssids);
4491
4492 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
4493 * Becasue of this, driver is assuming that this is not wildcard scan and so
4494 * is not aging out the scan results.
4495 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07004496 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07004497 {
4498 request->n_ssids = 0;
4499 }
4500
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004501 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07004502 {
4503 tCsrSSIDInfo *SsidInfo;
4504 int j;
4505 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
4506 /* Allocate num_ssid tCsrSSIDInfo structure */
4507 SsidInfo = scanRequest.SSIDs.SSIDList =
4508 ( tCsrSSIDInfo *)vos_mem_malloc(
4509 request->n_ssids*sizeof(tCsrSSIDInfo));
4510
4511 if(NULL == scanRequest.SSIDs.SSIDList)
4512 {
4513 hddLog(VOS_TRACE_LEVEL_ERROR,
4514 "memory alloc failed SSIDInfo buffer");
4515 return -ENOMEM;
4516 }
4517
4518 /* copy all the ssid's and their length */
4519 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
4520 {
4521 /* get the ssid length */
4522 SsidInfo->SSID.length = request->ssids[j].ssid_len;
4523 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
4524 SsidInfo->SSID.length);
4525 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
4526 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
4527 j, SsidInfo->SSID.ssId);
4528 }
4529 /* set the scan type to active */
4530 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4531 }
4532 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4533 {
4534 /* set the scan type to active */
4535 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4536 }
4537 else
4538 {
4539 /*Set the scan type to default type, in this case it is ACTIVE*/
4540 scanRequest.scanType = pScanInfo->scan_mode;
4541 }
4542 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
4543 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4544 }
4545 else
4546 {
4547 /* set the scan type to active */
4548 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4549 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4550
4551 /* set min and max channel time to zero */
4552 scanRequest.minChnTime = 0;
4553 scanRequest.maxChnTime = 0;
4554 }
4555
4556 /* set BSSType to default type */
4557 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4558
4559 /*TODO: scan the requested channels only*/
4560
4561 /*Right now scanning all the channels */
4562 if( request )
4563 {
4564 if( request->n_channels )
4565 {
4566 channelList = vos_mem_malloc( request->n_channels );
4567 if( NULL == channelList )
4568 {
4569 status = -ENOMEM;
4570 goto free_mem;
4571 }
4572
4573 for( i = 0 ; i < request->n_channels ; i++ )
4574 channelList[i] = request->channels[i]->hw_value;
4575 }
4576
4577 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4578 scanRequest.ChannelInfo.ChannelList = channelList;
4579
4580 /* set requestType to full scan */
4581 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004582
4583 /* Flush the scan results(only p2p beacons) for STA scan and P2P
4584 * search (Flush on both full scan and social scan but not on single
4585 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
4586 */
4587
4588 /* Supplicant does single channel scan after 8-way handshake
4589 * and in that case driver shoudnt flush scan results. If
4590 * driver flushes the scan results here and unfortunately if
4591 * the AP doesnt respond to our probe req then association
4592 * fails which is not desired
4593 */
4594
4595 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4596 {
4597 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4598 pAdapter->sessionId );
4599 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004600
4601 if( request->ie_len )
4602 {
4603 /* save this for future association (join requires this) */
4604 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4605 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4606 pScanInfo->scanAddIE.length = request->ie_len;
4607
4608 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004609 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4610 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004611 )
4612 {
4613 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4614 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4615 }
4616
4617 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4618 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4619
Jeff Johnson295189b2012-06-20 16:38:30 -07004620 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4621 request->ie_len);
4622 if (pP2pIe != NULL)
4623 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004624#ifdef WLAN_FEATURE_P2P_DEBUG
4625 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4626 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4627 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4628 {
4629 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4630 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4631 "Go nego completed to Connection is started");
4632 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4633 "for 8way Handshake");
4634 }
4635 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4636 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4637 {
4638 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4639 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4640 "Disconnected state to Connection is started");
4641 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4642 "for 4way Handshake");
4643 }
4644#endif
4645
Jeff Johnsone7245742012-09-05 17:12:55 -07004646 /* no_cck will be set during p2p find to disable 11b rates */
4647 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004648 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004649 hddLog(VOS_TRACE_LEVEL_INFO,
4650 "%s: This is a P2P Search", __func__);
4651 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004652
Jeff Johnsone7245742012-09-05 17:12:55 -07004653 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4654 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004655 /* set requestType to P2P Discovery */
4656 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004657 }
4658
4659 /*
4660 Skip Dfs Channel in case of P2P Search
4661 if it is set in ini file
4662 */
4663 if(cfg_param->skipDfsChnlInP2pSearch)
4664 {
4665 scanRequest.skipDfsChnlInP2pSearch = 1;
4666 }
4667 else
4668 {
4669 scanRequest.skipDfsChnlInP2pSearch = 0;
4670 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004671
Jeff Johnson295189b2012-06-20 16:38:30 -07004672 }
4673 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004674 }
4675 }
4676
4677 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4678
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004679 /* acquire the wakelock to avoid the apps suspend during the scan. To
4680 * address the following issues.
4681 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4682 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4683 * for long time, this result in apps running at full power for long time.
4684 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4685 * be stuck in full power because of resume BMPS
4686 */
4687 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004688
4689 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004690 pAdapter->sessionId, &scanRequest, &scanId,
4691 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004692
Jeff Johnson295189b2012-06-20 16:38:30 -07004693 if (eHAL_STATUS_SUCCESS != status)
4694 {
4695 hddLog(VOS_TRACE_LEVEL_ERROR,
4696 "%s: sme_ScanRequest returned error %d", __func__, status);
4697 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004698 if(eHAL_STATUS_RESOURCES == status)
4699 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004700 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 -07004701 status = -EBUSY;
4702 } else {
4703 status = -EIO;
4704 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004705 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004706 goto free_mem;
4707 }
4708
4709 pScanInfo->mScanPending = TRUE;
4710 pAdapter->request = request;
4711 pScanInfo->scanId = scanId;
4712
4713 complete(&pScanInfo->scan_req_completion_event);
4714
4715free_mem:
4716 if( scanRequest.SSIDs.SSIDList )
4717 {
4718 vos_mem_free(scanRequest.SSIDs.SSIDList);
4719 }
4720
4721 if( channelList )
4722 vos_mem_free( channelList );
4723
4724 EXIT();
4725
4726 return status;
4727}
4728
4729/*
4730 * FUNCTION: wlan_hdd_cfg80211_connect_start
4731 * This function is used to start the association process
4732 */
4733int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004734 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004735{
4736 int status = 0;
4737 hdd_wext_state_t *pWextState;
4738 v_U32_t roamId;
4739 tCsrRoamProfile *pRoamProfile;
4740 eMib_dot11DesiredBssType connectedBssType;
4741 eCsrAuthType RSNAuthType;
4742
4743 ENTER();
4744
4745 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4746
4747 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4748 {
4749 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4750 return -EINVAL;
4751 }
4752
4753 pRoamProfile = &pWextState->roamProfile;
4754
4755 if (pRoamProfile)
4756 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004757 int ret = 0;
4758 hdd_station_ctx_t *pHddStaCtx;
4759 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4760 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4761
4762 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4763 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4764 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004765 {
4766 /* Issue disconnect to CSR */
4767 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4768 if( eHAL_STATUS_SUCCESS ==
4769 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4770 pAdapter->sessionId,
4771 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4772 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004773 ret = wait_for_completion_interruptible_timeout(
4774 &pAdapter->disconnect_comp_var,
4775 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4776 if (0 == ret)
4777 {
4778 VOS_ASSERT(0);
4779 }
4780 }
4781 }
4782 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4783 {
4784 ret = wait_for_completion_interruptible_timeout(
4785 &pAdapter->disconnect_comp_var,
4786 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4787 if (0 == ret)
4788 {
4789 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004790 }
4791 }
4792
4793 if (HDD_WMM_USER_MODE_NO_QOS ==
4794 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4795 {
4796 /*QoS not enabled in cfg file*/
4797 pRoamProfile->uapsd_mask = 0;
4798 }
4799 else
4800 {
4801 /*QoS enabled, update uapsd mask from cfg file*/
4802 pRoamProfile->uapsd_mask =
4803 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4804 }
4805
4806 pRoamProfile->SSIDs.numOfSSIDs = 1;
4807 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4808 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
4809 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
4810 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4811 ssid, ssid_len);
4812
4813 if (bssid)
4814 {
4815 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4816 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4817 WNI_CFG_BSSID_LEN);
4818 /* Save BSSID in seperate variable as well, as RoamProfile
4819 BSSID is getting zeroed out in the association process. And in
4820 case of join failure we should send valid BSSID to supplicant
4821 */
4822 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4823 WNI_CFG_BSSID_LEN);
4824 }
4825
4826 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4827 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4828 {
4829 /*set gen ie*/
4830 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4831 /*set auth*/
4832 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4833 }
4834 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4835 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4836 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4837 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4838 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4839 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4840 )
4841 {
4842 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4843 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4844 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4845 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4846 eCSR_AUTH_TYPE_AUTOSWITCH;
4847 pWextState->roamProfile.AuthType.authType[0] =
4848 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4849 }
4850#ifdef FEATURE_WLAN_WAPI
4851 if (pAdapter->wapi_info.nWapiMode)
4852 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004853 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004854 switch (pAdapter->wapi_info.wapiAuthMode)
4855 {
4856 case WAPI_AUTH_MODE_PSK:
4857 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004858 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004859 pAdapter->wapi_info.wapiAuthMode);
4860 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4861 break;
4862 }
4863 case WAPI_AUTH_MODE_CERT:
4864 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004865 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004866 pAdapter->wapi_info.wapiAuthMode);
4867 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4868 break;
4869 }
4870 } // End of switch
4871 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4872 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4873 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004874 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004875 pRoamProfile->AuthType.numEntries = 1;
4876 pRoamProfile->EncryptionType.numEntries = 1;
4877 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4878 pRoamProfile->mcEncryptionType.numEntries = 1;
4879 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4880 }
4881 }
4882#endif /* FEATURE_WLAN_WAPI */
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05304883#ifdef WLAN_FEATURE_GTK_OFFLOAD
4884 /* Initializing gtkOffloadRequestParams */
4885 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4886 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4887 {
4888 pHddStaCtx->gtkOffloadRequestParams.requested = FALSE;
4889 memset(&pHddStaCtx->gtkOffloadRequestParams.gtkOffloadReqParams,
4890 0, sizeof (tSirGtkOffloadParams));
4891 }
4892#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004893 pRoamProfile->csrPersona = pAdapter->device_mode;
4894
Jeff Johnson32d95a32012-09-10 13:15:23 -07004895 if( operatingChannel )
4896 {
4897 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4898 pRoamProfile->ChannelInfo.numOfChannels = 1;
4899 }
Chet Lanctot186b5732013-03-18 10:26:30 -07004900 else
4901 {
4902 pRoamProfile->ChannelInfo.ChannelList = NULL;
4903 pRoamProfile->ChannelInfo.numOfChannels = 0;
4904 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004905
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004906 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
4907 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
4908 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
4909 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004910 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
4911 */
4912 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4913 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
4914 eConnectionState_Connecting);
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004915
Jeff Johnson295189b2012-06-20 16:38:30 -07004916 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4917 pAdapter->sessionId, pRoamProfile, &roamId);
4918
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004919 if( (eHAL_STATUS_SUCCESS != status) &&
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304920 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
4921
4922 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004923 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
4924 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
4925 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304926 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004927 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304928 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004929
4930 pRoamProfile->ChannelInfo.ChannelList = NULL;
4931 pRoamProfile->ChannelInfo.numOfChannels = 0;
4932
Jeff Johnson295189b2012-06-20 16:38:30 -07004933 }
4934 else
4935 {
4936 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4937 return -EINVAL;
4938 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004939 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004940 return status;
4941}
4942
4943/*
4944 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4945 * This function is used to set the authentication type (OPEN/SHARED).
4946 *
4947 */
4948static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4949 enum nl80211_auth_type auth_type)
4950{
4951 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4952 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4953
4954 ENTER();
4955
4956 /*set authentication type*/
4957 switch (auth_type)
4958 {
4959 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4960 case NL80211_AUTHTYPE_AUTOMATIC:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07004961#ifdef WLAN_FEATURE_VOWIFI_11R
4962 case NL80211_AUTHTYPE_FT:
4963#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07004964 hddLog(VOS_TRACE_LEVEL_INFO,
4965 "%s: set authentication type to OPEN", __func__);
4966 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4967 break;
4968
4969 case NL80211_AUTHTYPE_SHARED_KEY:
4970 hddLog(VOS_TRACE_LEVEL_INFO,
4971 "%s: set authentication type to SHARED", __func__);
4972 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4973 break;
4974#ifdef FEATURE_WLAN_CCX
4975 case NL80211_AUTHTYPE_NETWORK_EAP:
4976 hddLog(VOS_TRACE_LEVEL_INFO,
4977 "%s: set authentication type to CCKM WPA", __func__);
4978 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4979 break;
4980#endif
4981
4982
4983 default:
4984 hddLog(VOS_TRACE_LEVEL_ERROR,
4985 "%s: Unsupported authentication type %d", __func__,
4986 auth_type);
4987 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4988 return -EINVAL;
4989 }
4990
4991 pWextState->roamProfile.AuthType.authType[0] =
4992 pHddStaCtx->conn_info.authType;
4993 return 0;
4994}
4995
4996/*
4997 * FUNCTION: wlan_hdd_set_akm_suite
4998 * This function is used to set the key mgmt type(PSK/8021x).
4999 *
5000 */
5001static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
5002 u32 key_mgmt
5003 )
5004{
5005 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5006 ENTER();
5007
5008 /*set key mgmt type*/
5009 switch(key_mgmt)
5010 {
5011 case WLAN_AKM_SUITE_PSK:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05305012#ifdef WLAN_FEATURE_VOWIFI_11R
5013 case WLAN_AKM_SUITE_FT_PSK:
5014#endif
5015 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
Jeff Johnson295189b2012-06-20 16:38:30 -07005016 __func__);
5017 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
5018 break;
5019
5020 case WLAN_AKM_SUITE_8021X:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05305021#ifdef WLAN_FEATURE_VOWIFI_11R
5022 case WLAN_AKM_SUITE_FT_8021X:
5023#endif
5024 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
Jeff Johnson295189b2012-06-20 16:38:30 -07005025 __func__);
5026 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
5027 break;
5028#ifdef FEATURE_WLAN_CCX
5029#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
5030#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
5031 case WLAN_AKM_SUITE_CCKM:
5032 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
5033 __func__);
5034 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
5035 break;
5036#endif
5037
5038 default:
5039 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
5040 __func__, key_mgmt);
5041 return -EINVAL;
5042
5043 }
5044 return 0;
5045}
5046
5047/*
5048 * FUNCTION: wlan_hdd_cfg80211_set_cipher
5049 * This function is used to set the encryption type
5050 * (NONE/WEP40/WEP104/TKIP/CCMP).
5051 */
5052static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
5053 u32 cipher,
5054 bool ucast
5055 )
5056{
5057 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5058 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5059 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5060
5061 ENTER();
5062
5063 if (!cipher)
5064 {
5065 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
5066 __func__, cipher);
5067 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5068 }
5069 else
5070 {
5071
5072 /*set encryption method*/
5073 switch (cipher)
5074 {
5075 case IW_AUTH_CIPHER_NONE:
5076 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5077 break;
5078
5079 case WLAN_CIPHER_SUITE_WEP40:
5080 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
5081 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
5082 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
5083 else
5084 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5085 break;
5086
5087 case WLAN_CIPHER_SUITE_WEP104:
5088 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
5089 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
5090 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
5091 else
5092 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
5093 break;
5094
5095 case WLAN_CIPHER_SUITE_TKIP:
5096 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5097 break;
5098
5099 case WLAN_CIPHER_SUITE_CCMP:
5100 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5101 break;
5102#ifdef FEATURE_WLAN_WAPI
5103 case WLAN_CIPHER_SUITE_SMS4:
5104 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
5105 break;
5106#endif
5107
5108#ifdef FEATURE_WLAN_CCX
5109 case WLAN_CIPHER_SUITE_KRK:
5110 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
5111 break;
5112#endif
5113 default:
5114 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
5115 __func__, cipher);
5116 return -EOPNOTSUPP;
5117 }
5118 }
5119
5120 if (ucast)
5121 {
5122 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
5123 __func__, encryptionType);
5124 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5125 pWextState->roamProfile.EncryptionType.numEntries = 1;
5126 pWextState->roamProfile.EncryptionType.encryptionType[0] =
5127 encryptionType;
5128 }
5129 else
5130 {
5131 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
5132 __func__, encryptionType);
5133 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
5134 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
5135 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
5136 }
5137
5138 return 0;
5139}
5140
5141
5142/*
5143 * FUNCTION: wlan_hdd_cfg80211_set_ie
5144 * This function is used to parse WPA/RSN IE's.
5145 */
5146int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
5147 u8 *ie,
5148 size_t ie_len
5149 )
5150{
5151 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5152 u8 *genie = ie;
5153 v_U16_t remLen = ie_len;
5154#ifdef FEATURE_WLAN_WAPI
5155 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
5156 u16 *tmp;
5157 v_U16_t akmsuiteCount;
5158 int *akmlist;
5159#endif
5160 ENTER();
5161
5162 /* clear previous assocAddIE */
5163 pWextState->assocAddIE.length = 0;
5164 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
5165
5166 while (remLen >= 2)
5167 {
5168 v_U16_t eLen = 0;
5169 v_U8_t elementId;
5170 elementId = *genie++;
5171 eLen = *genie++;
5172 remLen -= 2;
5173
5174 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
5175 __func__, elementId, eLen);
5176
5177 switch ( elementId )
5178 {
5179 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005180 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 -07005181 {
5182 hddLog(VOS_TRACE_LEVEL_ERROR,
5183 "%s: Invalid WPA IE", __func__);
5184 return -EINVAL;
5185 }
5186 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
5187 {
5188 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5189 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
5190 __func__, eLen + 2);
5191
5192 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5193 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005194 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
5195 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005196 VOS_ASSERT(0);
5197 return -ENOMEM;
5198 }
5199 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5200 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5201 pWextState->assocAddIE.length += eLen + 2;
5202
5203 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
5204 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5205 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5206 }
5207 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
5208 {
5209 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
5210 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5211 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
5212 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
5213 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
5214 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005215 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
5216 P2P_OUI_TYPE_SIZE))
5217 /*Consider P2P IE, only for P2P Client */
5218 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5219 {
5220 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5221 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
5222 __func__, eLen + 2);
5223
5224 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5225 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005226 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5227 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005228 VOS_ASSERT(0);
5229 return -ENOMEM;
5230 }
5231 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5232 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5233 pWextState->assocAddIE.length += eLen + 2;
5234
5235 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5236 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5237 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005238#ifdef WLAN_FEATURE_WFD
5239 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
5240 WFD_OUI_TYPE_SIZE))
5241 /*Consider WFD 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 WFD 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 // WFD IE is saved to Additional IE ; it should be accumulated to handle
5256 // WPS IE + P2P IE + WFD IE
5257 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5258 pWextState->assocAddIE.length += eLen + 2;
5259
5260 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5261 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5262 }
5263#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005264 /* Appending HS 2.0 Indication Element in Assiciation Request */
5265 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005266 HS20_OUI_TYPE_SIZE)) )
5267 {
5268 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5269 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
5270 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005271
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005272 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");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005276 VOS_ASSERT(0);
5277 return -ENOMEM;
5278 }
5279 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5280 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005281
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005282 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5283 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5284 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005285
Jeff Johnson295189b2012-06-20 16:38:30 -07005286 break;
5287 case DOT11F_EID_RSN:
5288 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
5289 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5290 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
5291 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
5292 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
5293 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005294 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
5295 case DOT11F_EID_EXTCAP:
5296 {
5297 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5298 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
5299 __func__, eLen + 2);
5300
5301 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5302 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005303 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5304 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005305 VOS_ASSERT(0);
5306 return -ENOMEM;
5307 }
5308 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5309 pWextState->assocAddIE.length += eLen + 2;
5310
5311 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5312 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5313 break;
5314 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005315#ifdef FEATURE_WLAN_WAPI
5316 case WLAN_EID_WAPI:
5317 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
5318 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
5319 pAdapter->wapi_info.nWapiMode);
5320 tmp = (u16 *)ie;
5321 tmp = tmp + 2; // Skip element Id and Len, Version
5322 akmsuiteCount = WPA_GET_LE16(tmp);
5323 tmp = tmp + 1;
5324 akmlist = (int *)(tmp);
5325 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
5326 {
5327 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
5328 }
5329 else
5330 {
5331 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
5332 VOS_ASSERT(0);
5333 return -EINVAL;
5334 }
5335
5336 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
5337 {
5338 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005339 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005340 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
5341 }
5342 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
5343 {
5344 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005345 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005346 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
5347 }
5348 break;
5349#endif
5350 default:
5351 hddLog (VOS_TRACE_LEVEL_ERROR,
5352 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005353 /* when Unknown IE is received we should break and continue
5354 * to the next IE in the buffer instead we were returning
5355 * so changing this to break */
5356 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005357 }
5358 genie += eLen;
5359 remLen -= eLen;
5360 }
5361 EXIT();
5362 return 0;
5363}
5364
5365/*
5366 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5367 * This function is used to initialize the security
5368 * parameters during connect operation.
5369 */
5370int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
5371 struct cfg80211_connect_params *req
5372 )
5373{
5374 int status = 0;
5375 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5376 ENTER();
5377
5378 /*set wpa version*/
5379 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5380
5381 if (req->crypto.wpa_versions)
5382 {
5383 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
5384 && ( (req->ie_len)
5385 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
5386 // Make sure that it is including a WPA IE.
5387 /* Currently NL is putting WPA version 1 even for open,
5388 * since p2p ie is also put in same buffer.
5389 * */
5390 {
5391 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5392 }
5393 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
5394 {
5395 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5396 }
5397 }
5398
5399 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
5400 pWextState->wpaVersion);
5401
5402 /*set authentication type*/
5403 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
5404
5405 if (0 > status)
5406 {
5407 hddLog(VOS_TRACE_LEVEL_ERROR,
5408 "%s: failed to set authentication type ", __func__);
5409 return status;
5410 }
5411
5412 /*set key mgmt type*/
5413 if (req->crypto.n_akm_suites)
5414 {
5415 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
5416 if (0 > status)
5417 {
5418 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
5419 __func__);
5420 return status;
5421 }
5422 }
5423
5424 /*set pairwise cipher type*/
5425 if (req->crypto.n_ciphers_pairwise)
5426 {
5427 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
5428 req->crypto.ciphers_pairwise[0], true);
5429 if (0 > status)
5430 {
5431 hddLog(VOS_TRACE_LEVEL_ERROR,
5432 "%s: failed to set unicast cipher type", __func__);
5433 return status;
5434 }
5435 }
5436 else
5437 {
5438 /*Reset previous cipher suite to none*/
5439 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
5440 if (0 > status)
5441 {
5442 hddLog(VOS_TRACE_LEVEL_ERROR,
5443 "%s: failed to set unicast cipher type", __func__);
5444 return status;
5445 }
5446 }
5447
5448 /*set group cipher type*/
5449 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
5450 false);
5451
5452 if (0 > status)
5453 {
5454 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
5455 __func__);
5456 return status;
5457 }
5458
Chet Lanctot186b5732013-03-18 10:26:30 -07005459#ifdef WLAN_FEATURE_11W
5460 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
5461#endif
5462
Jeff Johnson295189b2012-06-20 16:38:30 -07005463 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
5464 if (req->ie_len)
5465 {
5466 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
5467 if ( 0 > status)
5468 {
5469 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
5470 __func__);
5471 return status;
5472 }
5473 }
5474
5475 /*incase of WEP set default key information*/
5476 if (req->key && req->key_len)
5477 {
5478 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
5479 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
5480 )
5481 {
5482 if ( IW_AUTH_KEY_MGMT_802_1X
5483 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
5484 {
5485 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
5486 __func__);
5487 return -EOPNOTSUPP;
5488 }
5489 else
5490 {
5491 u8 key_len = req->key_len;
5492 u8 key_idx = req->key_idx;
5493
5494 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
5495 && (CSR_MAX_NUM_KEY > key_idx)
5496 )
5497 {
5498 hddLog(VOS_TRACE_LEVEL_INFO,
5499 "%s: setting default wep key, key_idx = %hu key_len %hu",
5500 __func__, key_idx, key_len);
5501 vos_mem_copy(
5502 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
5503 req->key, key_len);
5504 pWextState->roamProfile.Keys.KeyLength[key_idx] =
5505 (u8)key_len;
5506 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
5507 }
5508 }
5509 }
5510 }
5511
5512 return status;
5513}
5514
5515/*
5516 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5517 * This function is used to initialize the security
5518 * parameters during connect operation.
5519 */
5520static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
5521 struct net_device *ndev,
5522 struct cfg80211_connect_params *req
5523 )
5524{
5525 int status = 0;
5526 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
5527 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
5528 hdd_context_t *pHddCtx = NULL;
5529
5530 ENTER();
5531
5532 hddLog(VOS_TRACE_LEVEL_INFO,
5533 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5534
5535 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5536 {
5537 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5538 "%s:LOGP in Progress. Ignore!!!", __func__);
5539 return -EAGAIN;
5540 }
5541
5542#ifdef WLAN_BTAMP_FEATURE
5543 //Infra connect not supported when AMP traffic is on.
5544 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
5545 {
5546 hddLog(VOS_TRACE_LEVEL_ERROR,
5547 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005548 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07005549 }
5550#endif
5551 /*initialise security parameters*/
5552 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
5553
5554 if ( 0 > status)
5555 {
5556 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
5557 __func__);
5558 return status;
5559 }
5560
5561 //If Device Mode is Station Concurrent Sessions Exit BMps
Jeff Johnsona8a1a482012-12-12 16:49:33 -08005562 //P2P Mode will be taken care in Open/close adapter
Jeff Johnson295189b2012-06-20 16:38:30 -07005563 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
5564 (vos_concurrent_sessions_running()))
5565 {
5566 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5567
5568 if (NULL != pVosContext)
5569 {
5570 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5571 if(NULL != pHddCtx)
5572 {
5573 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
5574 }
5575 }
5576 }
5577
Mohit Khanna765234a2012-09-11 15:08:35 -07005578 if ( req->channel )
5579 {
5580 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5581 req->ssid_len, req->bssid,
5582 req->channel->hw_value);
5583 }
5584 else
5585 {
5586 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5587 req->ssid_len, req->bssid,
5588 0);
5589 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005590
5591 if (0 > status)
5592 {
5593 //ReEnable BMPS if disabled
5594 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5595 (NULL != pHddCtx))
5596 {
5597 //ReEnable Bmps and Imps back
5598 hdd_enable_bmps_imps(pHddCtx);
5599 }
5600
5601 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5602 return status;
5603 }
5604 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
5605 EXIT();
5606 return status;
5607}
5608
5609
5610/*
5611 * FUNCTION: wlan_hdd_cfg80211_disconnect
5612 * This function is used to issue a disconnect request to SME
5613 */
5614static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
5615 struct net_device *dev,
5616 u16 reason
5617 )
5618{
5619 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5620 tCsrRoamProfile *pRoamProfile =
5621 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
5622 int status = 0;
5623 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005624#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005625 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005626 tANI_U8 staIdx;
5627#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005628
5629 ENTER();
5630
5631 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
5632 __func__,pAdapter->device_mode);
5633
5634 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5635 __func__, reason);
5636
5637 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
5638 {
5639 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5640 "%s:LOGP in Progress. Ignore!!!",__func__);
5641 return -EAGAIN;
5642 }
5643 if (NULL != pRoamProfile)
5644 {
5645 /*issue disconnect request to SME, if station is in connected state*/
5646 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
5647 {
5648 eCsrRoamDisconnectReason reasonCode =
5649 eCSR_DISCONNECT_REASON_UNSPECIFIED;
5650 switch(reason)
5651 {
5652 case WLAN_REASON_MIC_FAILURE:
5653 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
5654 break;
5655
5656 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
5657 case WLAN_REASON_DISASSOC_AP_BUSY:
5658 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
5659 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
5660 break;
5661
5662 case WLAN_REASON_PREV_AUTH_NOT_VALID:
5663 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
5664 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
5665 break;
5666
5667 case WLAN_REASON_DEAUTH_LEAVING:
5668 default:
5669 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
5670 break;
5671 }
5672 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5673 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
5674 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5675
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005676#ifdef FEATURE_WLAN_TDLS
5677 /* First clean up the tdls peers if any */
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005678 for (staIdx = 0 ; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005679 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005680 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId == pAdapter->sessionId) &&
5681 (pHddCtx->tdlsConnInfo[staIdx].staId))
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005682 {
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005683 uint8 *mac;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005684 mac = pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005685 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07005686 "%s: call sme_DeleteTdlsPeerSta staId %d sessionId %d " MAC_ADDRESS_STR,
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005687 __func__, pHddCtx->tdlsConnInfo[staIdx].staId, pAdapter->sessionId,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07005688 MAC_ADDR_ARRAY(mac));
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005689 sme_DeleteTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005690 pAdapter->sessionId,
5691 mac);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005692 }
5693 }
5694#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005695 /*issue disconnect*/
5696 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5697 pAdapter->sessionId, reasonCode);
5698
5699 if ( 0 != status)
5700 {
5701 hddLog(VOS_TRACE_LEVEL_ERROR,
5702 "%s csrRoamDisconnect failure, returned %d \n",
5703 __func__, (int)status );
5704 return -EINVAL;
5705 }
5706
5707 wait_for_completion_interruptible_timeout(
5708 &pAdapter->disconnect_comp_var,
5709 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5710
5711
5712 /*stop tx queues*/
5713 netif_tx_disable(dev);
5714 netif_carrier_off(dev);
5715 }
5716 }
5717 else
5718 {
5719 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
5720 }
5721
5722 return status;
5723}
5724
5725/*
5726 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
5727 * This function is used to initialize the security
5728 * settings in IBSS mode.
5729 */
5730static int wlan_hdd_cfg80211_set_privacy_ibss(
5731 hdd_adapter_t *pAdapter,
5732 struct cfg80211_ibss_params *params
5733 )
5734{
5735 int status = 0;
5736 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5737 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5738 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5739
5740 ENTER();
5741
5742 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5743
5744 if (params->ie_len && ( NULL != params->ie) )
5745 {
5746 if (WLAN_EID_RSN == params->ie[0])
5747 {
5748 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5749 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5750 }
5751 else
5752 {
5753 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5754 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5755 }
5756 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
5757
5758 if (0 > status)
5759 {
5760 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
5761 __func__);
5762 return status;
5763 }
5764 }
5765
5766 pWextState->roamProfile.AuthType.authType[0] =
5767 pHddStaCtx->conn_info.authType =
5768 eCSR_AUTH_TYPE_OPEN_SYSTEM;
5769
5770 if (params->privacy)
5771 {
5772 /* Security enabled IBSS, At this time there is no information available
5773 * about the security paramters, so initialise the encryption type to
5774 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
5775 * The correct security parameters will be updated later in
5776 * wlan_hdd_cfg80211_add_key */
5777 /* Hal expects encryption type to be set inorder
5778 *enable privacy bit in beacons */
5779
5780 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5781 }
5782
5783 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5784 pWextState->roamProfile.EncryptionType.numEntries = 1;
5785 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
5786
5787 return status;
5788}
5789
5790/*
5791 * FUNCTION: wlan_hdd_cfg80211_join_ibss
5792 * This function is used to create/join an IBSS
5793 */
5794static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
5795 struct net_device *dev,
5796 struct cfg80211_ibss_params *params
5797 )
5798{
5799 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5800 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5801 tCsrRoamProfile *pRoamProfile;
5802 int status;
5803 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5804
5805 ENTER();
5806
5807 hddLog(VOS_TRACE_LEVEL_INFO,
5808 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5809
5810 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5811 {
5812 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5813 "%s:LOGP in Progress. Ignore!!!", __func__);
5814 return -EAGAIN;
5815 }
5816
5817 if (NULL == pWextState)
5818 {
5819 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5820 __func__);
5821 return -EIO;
5822 }
5823
5824 pRoamProfile = &pWextState->roamProfile;
5825
5826 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
5827 {
5828 hddLog (VOS_TRACE_LEVEL_ERROR,
5829 "%s Interface type is not set to IBSS \n", __func__);
5830 return -EINVAL;
5831 }
5832
5833 /* Set Channel */
5834 if (NULL != params->channel)
5835 {
5836 u8 channelNum;
5837 if (IEEE80211_BAND_5GHZ == params->channel->band)
5838 {
5839 hddLog(VOS_TRACE_LEVEL_ERROR,
5840 "%s: IBSS join is called with unsupported band %d",
5841 __func__, params->channel->band);
5842 return -EOPNOTSUPP;
5843 }
5844
5845 /* Get channel number */
5846 channelNum =
5847 ieee80211_frequency_to_channel(params->channel->center_freq);
5848
5849 /*TODO: use macro*/
5850 if (14 >= channelNum)
5851 {
5852 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5853 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5854 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5855 int indx;
5856
5857 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5858 validChan, &numChans))
5859 {
5860 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
5861 __func__);
5862 return -EOPNOTSUPP;
5863 }
5864
5865 for (indx = 0; indx < numChans; indx++)
5866 {
5867 if (channelNum == validChan[indx])
5868 {
5869 break;
5870 }
5871 }
5872 if (indx >= numChans)
5873 {
5874 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
5875 __func__, channelNum);
5876 return -EINVAL;
5877 }
5878 /* Set the Operational Channel */
5879 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
5880 channelNum);
5881 pRoamProfile->ChannelInfo.numOfChannels = 1;
5882 pHddStaCtx->conn_info.operationChannel = channelNum;
5883 pRoamProfile->ChannelInfo.ChannelList =
5884 &pHddStaCtx->conn_info.operationChannel;
5885 }
5886 else
5887 {
5888 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5889 __func__, channelNum);
5890 return -EINVAL;
5891 }
5892 }
5893
5894 /* Initialize security parameters */
5895 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5896 if (status < 0)
5897 {
5898 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5899 __func__);
5900 return status;
5901 }
5902
5903 /* Issue connect start */
5904 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005905 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005906
5907 if (0 > status)
5908 {
5909 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5910 return status;
5911 }
5912
5913 return 0;
5914}
5915
5916/*
5917 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5918 * This function is used to leave an IBSS
5919 */
5920static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5921 struct net_device *dev
5922 )
5923{
5924 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5925 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5926 tCsrRoamProfile *pRoamProfile;
5927
5928 ENTER();
5929
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005930 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5931 {
5932 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5933 "%s:LOGP in Progress. Ignore!!!", __func__);
5934 return -EAGAIN;
5935 }
5936
Jeff Johnson295189b2012-06-20 16:38:30 -07005937 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5938 if (NULL == pWextState)
5939 {
5940 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5941 __func__);
5942 return -EIO;
5943 }
5944
5945 pRoamProfile = &pWextState->roamProfile;
5946
5947 /* Issue disconnect only if interface type is set to IBSS */
5948 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5949 {
5950 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5951 __func__);
5952 return -EINVAL;
5953 }
5954
5955 /* Issue Disconnect request */
5956 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5957 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5958 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5959
5960 return 0;
5961}
5962
5963/*
5964 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5965 * This function is used to set the phy parameters
5966 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5967 */
5968static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5969 u32 changed)
5970{
5971 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5972 tHalHandle hHal = pHddCtx->hHal;
5973
5974 ENTER();
5975
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005976 if ( pHddCtx->isLogpInProgress )
5977 {
5978 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5979 "%s:LOGP in Progress. Ignore!!!", __func__);
5980 return -EAGAIN;
5981 }
5982
Jeff Johnson295189b2012-06-20 16:38:30 -07005983 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
5984 {
5985 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
5986 WNI_CFG_RTS_THRESHOLD_STAMAX :
5987 wiphy->rts_threshold;
5988
5989 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
5990 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
5991 {
5992 hddLog(VOS_TRACE_LEVEL_ERROR,
5993 "%s: Invalid RTS Threshold value %hu",
5994 __func__, rts_threshold);
5995 return -EINVAL;
5996 }
5997
5998 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
5999 rts_threshold, ccmCfgSetCallback,
6000 eANI_BOOLEAN_TRUE))
6001 {
6002 hddLog(VOS_TRACE_LEVEL_ERROR,
6003 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
6004 __func__, rts_threshold);
6005 return -EIO;
6006 }
6007
6008 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
6009 rts_threshold);
6010 }
6011
6012 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
6013 {
6014 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
6015 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
6016 wiphy->frag_threshold;
6017
6018 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
6019 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
6020 {
6021 hddLog(VOS_TRACE_LEVEL_ERROR,
6022 "%s: Invalid frag_threshold value %hu", __func__,
6023 frag_threshold);
6024 return -EINVAL;
6025 }
6026
6027 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
6028 frag_threshold, ccmCfgSetCallback,
6029 eANI_BOOLEAN_TRUE))
6030 {
6031 hddLog(VOS_TRACE_LEVEL_ERROR,
6032 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
6033 __func__, frag_threshold);
6034 return -EIO;
6035 }
6036
6037 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
6038 frag_threshold);
6039 }
6040
6041 if ((changed & WIPHY_PARAM_RETRY_SHORT)
6042 || (changed & WIPHY_PARAM_RETRY_LONG))
6043 {
6044 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
6045 wiphy->retry_short :
6046 wiphy->retry_long;
6047
6048 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
6049 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
6050 {
6051 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
6052 __func__, retry_value);
6053 return -EINVAL;
6054 }
6055
6056 if (changed & WIPHY_PARAM_RETRY_SHORT)
6057 {
6058 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
6059 retry_value, ccmCfgSetCallback,
6060 eANI_BOOLEAN_TRUE))
6061 {
6062 hddLog(VOS_TRACE_LEVEL_ERROR,
6063 "%s: ccmCfgSetInt failed for long retry count %hu",
6064 __func__, retry_value);
6065 return -EIO;
6066 }
6067 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
6068 __func__, retry_value);
6069 }
6070 else if (changed & WIPHY_PARAM_RETRY_SHORT)
6071 {
6072 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
6073 retry_value, ccmCfgSetCallback,
6074 eANI_BOOLEAN_TRUE))
6075 {
6076 hddLog(VOS_TRACE_LEVEL_ERROR,
6077 "%s: ccmCfgSetInt failed for short retry count %hu",
6078 __func__, retry_value);
6079 return -EIO;
6080 }
6081 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
6082 __func__, retry_value);
6083 }
6084 }
6085
6086 return 0;
6087}
6088
6089/*
6090 * FUNCTION: wlan_hdd_cfg80211_set_txpower
6091 * This function is used to set the txpower
6092 */
6093static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
6094#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
6095 enum tx_power_setting type,
6096#else
6097 enum nl80211_tx_power_setting type,
6098#endif
6099 int dbm)
6100{
6101 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6102 tHalHandle hHal = pHddCtx->hHal;
6103 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
6104 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
6105
6106 ENTER();
6107
6108 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
6109 dbm, ccmCfgSetCallback,
6110 eANI_BOOLEAN_TRUE))
6111 {
6112 hddLog(VOS_TRACE_LEVEL_ERROR,
6113 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
6114 return -EIO;
6115 }
6116
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006117 if ( pHddCtx->isLogpInProgress )
6118 {
6119 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6120 "%s:LOGP in Progress. Ignore!!!", __func__);
6121 return -EAGAIN;
6122 }
6123
Jeff Johnson295189b2012-06-20 16:38:30 -07006124 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
6125 dbm);
6126
6127 switch(type)
6128 {
6129 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
6130 /* Fall through */
6131 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
6132 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
6133 {
6134 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
6135 __func__);
6136 return -EIO;
6137 }
6138 break;
6139 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
6140 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
6141 __func__);
6142 return -EOPNOTSUPP;
6143 break;
6144 default:
6145 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
6146 __func__, type);
6147 return -EIO;
6148 }
6149
6150 return 0;
6151}
6152
6153/*
6154 * FUNCTION: wlan_hdd_cfg80211_get_txpower
6155 * This function is used to read the txpower
6156 */
6157static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
6158{
6159
6160 hdd_adapter_t *pAdapter;
6161 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6162
Jeff Johnsone7245742012-09-05 17:12:55 -07006163 ENTER();
6164
Jeff Johnson295189b2012-06-20 16:38:30 -07006165 if (NULL == pHddCtx)
6166 {
6167 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
6168 *dbm = 0;
6169 return -ENOENT;
6170 }
6171
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006172 if ( pHddCtx->isLogpInProgress )
6173 {
6174 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6175 "%s:LOGP in Progress. Ignore!!!", __func__);
6176 return -EAGAIN;
6177 }
6178
Jeff Johnson295189b2012-06-20 16:38:30 -07006179 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
6180 if (NULL == pAdapter)
6181 {
6182 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
6183 return -ENOENT;
6184 }
6185
6186 wlan_hdd_get_classAstats(pAdapter);
6187 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
6188
Jeff Johnsone7245742012-09-05 17:12:55 -07006189 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006190 return 0;
6191}
6192
6193static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
6194 u8* mac, struct station_info *sinfo)
6195{
6196 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
6197 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6198 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
6199 tANI_U8 rate_flags;
6200
6201 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6202 hdd_config_t *pCfg = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07006203
6204 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
6205 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
6206 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
6207 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
6208 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
6209 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
6210 tANI_U16 maxRate = 0;
6211 tANI_U16 myRate;
6212 tANI_U16 currentRate = 0;
6213 tANI_U8 maxSpeedMCS = 0;
6214 tANI_U8 maxMCSIdx = 0;
6215 tANI_U8 rateFlag = 1;
6216 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006217 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07006218
Leo Chang6f8870f2013-03-26 18:11:36 -07006219#ifdef WLAN_FEATURE_11AC
6220 tANI_U32 vht_mcs_map;
6221 eDataRate11ACMaxMcs vhtMaxMcs;
6222#endif /* WLAN_FEATURE_11AC */
6223
Jeff Johnsone7245742012-09-05 17:12:55 -07006224 ENTER();
6225
Jeff Johnson295189b2012-06-20 16:38:30 -07006226 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
6227 (0 == ssidlen))
6228 {
6229 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
6230 " Invalid ssidlen, %d", __func__, ssidlen);
6231 /*To keep GUI happy*/
6232 return 0;
6233 }
6234
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006235 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6236 {
6237 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6238 "%s:LOGP in Progress. Ignore!!!", __func__);
6239 return -EAGAIN;
6240 }
6241
Jeff Johnson295189b2012-06-20 16:38:30 -07006242 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
6243 sinfo->filled |= STATION_INFO_SIGNAL;
6244
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006245 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006246 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
6247
6248 //convert to the UI units of 100kbps
6249 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
6250
6251#ifdef LINKSPEED_DEBUG_ENABLED
Leo Chang6f8870f2013-03-26 18:11:36 -07006252 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 -07006253 sinfo->signal,
6254 pCfg->reportMaxLinkSpeed,
6255 myRate,
6256 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006257 (int) pCfg->linkSpeedRssiMid,
6258 (int) pCfg->linkSpeedRssiLow,
Leo Chang6f8870f2013-03-26 18:11:36 -07006259 (int) rate_flags,
6260 (int) pAdapter->hdd_stats.ClassA_stat.mcs_index);
Jeff Johnson295189b2012-06-20 16:38:30 -07006261#endif //LINKSPEED_DEBUG_ENABLED
6262
6263 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
6264 {
6265 // we do not want to necessarily report the current speed
6266 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
6267 {
6268 // report the max possible speed
6269 rssidx = 0;
6270 }
6271 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
6272 {
6273 // report the max possible speed with RSSI scaling
6274 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
6275 {
6276 // report the max possible speed
6277 rssidx = 0;
6278 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006279 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07006280 {
6281 // report middle speed
6282 rssidx = 1;
6283 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006284 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
6285 {
6286 // report middle speed
6287 rssidx = 2;
6288 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006289 else
6290 {
6291 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006292 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07006293 }
6294 }
6295 else
6296 {
6297 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
6298 hddLog(VOS_TRACE_LEVEL_ERROR,
6299 "%s: Invalid value for reportMaxLinkSpeed: %u",
6300 __func__, pCfg->reportMaxLinkSpeed);
6301 rssidx = 0;
6302 }
6303
6304 maxRate = 0;
6305
6306 /* Get Basic Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306307 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_OPERATIONAL_RATE_SET,
6308 OperationalRates, &ORLeng))
6309 {
6310 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6311 /*To keep GUI happy*/
6312 return 0;
6313 }
6314
Jeff Johnson295189b2012-06-20 16:38:30 -07006315 for (i = 0; i < ORLeng; i++)
6316 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006317 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006318 {
6319 /* Validate Rate Set */
6320 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
6321 {
6322 currentRate = supported_data_rate[j].supported_rate[rssidx];
6323 break;
6324 }
6325 }
6326 /* Update MAX rate */
6327 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6328 }
6329
6330 /* Get Extended Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306331 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
6332 ExtendedRates, &ERLeng))
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 < ERLeng; 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 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
6344 {
6345 currentRate = supported_data_rate[j].supported_rate[rssidx];
6346 break;
6347 }
6348 }
6349 /* Update MAX rate */
6350 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6351 }
6352
6353 /* Get MCS Rate Set -- but only if we are connected at MCS
6354 rates or if we are always reporting max speed or if we have
6355 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006356 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07006357 {
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306358 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_CURRENT_MCS_SET,
6359 MCSRates, &MCSLeng))
6360 {
6361 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6362 /*To keep GUI happy*/
6363 return 0;
6364 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006365 rateFlag = 0;
Leo Chang6f8870f2013-03-26 18:11:36 -07006366#ifdef WLAN_FEATURE_11AC
6367 /* VHT80 rate has seperate rate table */
6368 if (rate_flags & eHAL_TX_RATE_VHT80)
Jeff Johnson295189b2012-06-20 16:38:30 -07006369 {
Leo Chang6f8870f2013-03-26 18:11:36 -07006370 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_rate[rateFlag];
6371 ccmCfgGetInt(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_VHT_TX_MCS_MAP, &vht_mcs_map);
6372 if (rate_flags & eHAL_TX_RATE_SGI)
Jeff Johnson295189b2012-06-20 16:38:30 -07006373 {
Leo Chang6f8870f2013-03-26 18:11:36 -07006374 rateFlag |= 1;
Jeff Johnson295189b2012-06-20 16:38:30 -07006375 }
Leo Chang6f8870f2013-03-26 18:11:36 -07006376 vhtMaxMcs = (eDataRate11ACMaxMcs)(vht_mcs_map & DATA_RATE_11AC_MCS_MASK);
6377 if (DATA_RATE_11AC_MAX_MCS_7 == vhtMaxMcs)
Jeff Johnson295189b2012-06-20 16:38:30 -07006378 {
Leo Chang6f8870f2013-03-26 18:11:36 -07006379 maxMCSIdx = 7;
6380 }
6381 else if (DATA_RATE_11AC_MAX_MCS_8 == vhtMaxMcs)
6382 {
6383 maxMCSIdx = 8;
6384 }
6385 else if (DATA_RATE_11AC_MAX_MCS_9 == vhtMaxMcs)
6386 {
6387 maxMCSIdx = 9;
6388 }
6389 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_rate[rateFlag];
6390 maxSpeedMCS = 1;
6391 if (currentRate > maxRate)
6392 {
6393 maxRate = currentRate;
6394 }
6395 }
6396 else
6397#endif /* WLAN_FEATURE_11AC */
6398 {
6399 if (rate_flags & eHAL_TX_RATE_HT40)
6400 {
6401 rateFlag |= 1;
6402 }
6403 if (rate_flags & eHAL_TX_RATE_SGI)
6404 {
6405 rateFlag |= 2;
6406 }
6407
6408 for (i = 0; i < MCSLeng; i++)
6409 {
6410 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
6411 for (j = 0; j < temp; j++)
6412 {
6413 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
6414 {
6415 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
6416 break;
6417 }
6418 }
6419 if ((j < temp) && (currentRate > maxRate))
6420 {
6421 maxRate = currentRate;
6422 maxSpeedMCS = 1;
6423 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
6424 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006425 }
6426 }
6427 }
6428
6429 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006430 if (((maxRate < myRate) && (0 == rssidx)) ||
6431 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006432 {
6433 maxRate = myRate;
6434 if (rate_flags & eHAL_TX_RATE_LEGACY)
6435 {
6436 maxSpeedMCS = 0;
6437 }
6438 else
6439 {
6440 maxSpeedMCS = 1;
6441 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6442 }
6443 }
6444
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006445 if ((!maxSpeedMCS) || (0 != rssidx))
Jeff Johnson295189b2012-06-20 16:38:30 -07006446 {
6447 sinfo->txrate.legacy = maxRate;
6448#ifdef LINKSPEED_DEBUG_ENABLED
6449 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
6450#endif //LINKSPEED_DEBUG_ENABLED
6451 }
6452 else
6453 {
6454 sinfo->txrate.mcs = maxMCSIdx;
Leo Chang6f8870f2013-03-26 18:11:36 -07006455#ifdef WLAN_FEATURE_11AC
6456 sinfo->txrate.nss = 1;
6457 if (rate_flags & eHAL_TX_RATE_VHT80)
6458 {
6459 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
6460 }
6461 else
6462#endif /* WLAN_FEATURE_11AC */
6463 {
6464 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6465 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006466 if (rate_flags & eHAL_TX_RATE_SGI)
6467 {
6468 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6469 }
6470 if (rate_flags & eHAL_TX_RATE_HT40)
6471 {
6472 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6473 }
Leo Chang6f8870f2013-03-26 18:11:36 -07006474#ifdef WLAN_FEATURE_11AC
6475 else if (rate_flags & eHAL_TX_RATE_VHT80)
6476 {
6477 sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
6478 }
6479#endif /* WLAN_FEATURE_11AC */
Jeff Johnson295189b2012-06-20 16:38:30 -07006480#ifdef LINKSPEED_DEBUG_ENABLED
6481 pr_info("Reporting MCS rate %d flags %x\n",
6482 sinfo->txrate.mcs,
6483 sinfo->txrate.flags );
6484#endif //LINKSPEED_DEBUG_ENABLED
6485 }
6486 }
6487 else
6488 {
6489 // report current rate instead of max rate
6490
6491 if (rate_flags & eHAL_TX_RATE_LEGACY)
6492 {
6493 //provide to the UI in units of 100kbps
6494 sinfo->txrate.legacy = myRate;
6495#ifdef LINKSPEED_DEBUG_ENABLED
6496 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
6497#endif //LINKSPEED_DEBUG_ENABLED
6498 }
6499 else
6500 {
6501 //must be MCS
6502 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
Leo Chang6f8870f2013-03-26 18:11:36 -07006503#ifdef WLAN_FEATURE_11AC
6504 sinfo->txrate.nss = 1;
6505 if (rate_flags & eHAL_TX_RATE_VHT80)
6506 {
6507 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
6508 }
6509 else
6510#endif /* WLAN_FEATURE_11AC */
6511 {
6512 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6513 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006514 if (rate_flags & eHAL_TX_RATE_SGI)
6515 {
6516 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6517 }
6518 if (rate_flags & eHAL_TX_RATE_HT40)
6519 {
6520 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6521 }
Leo Chang6f8870f2013-03-26 18:11:36 -07006522#ifdef WLAN_FEATURE_11AC
6523 else if (rate_flags & eHAL_TX_RATE_VHT80)
6524 {
6525 sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
6526 }
6527#endif /* WLAN_FEATURE_11AC */
Jeff Johnson295189b2012-06-20 16:38:30 -07006528#ifdef LINKSPEED_DEBUG_ENABLED
6529 pr_info("Reporting actual MCS rate %d flags %x\n",
6530 sinfo->txrate.mcs,
6531 sinfo->txrate.flags );
6532#endif //LINKSPEED_DEBUG_ENABLED
6533 }
6534 }
6535 sinfo->filled |= STATION_INFO_TX_BITRATE;
6536
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006537 sinfo->tx_packets =
6538 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
6539 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
6540 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
6541 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
6542
6543 sinfo->tx_retries =
6544 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
6545 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
6546 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
6547 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
6548
6549 sinfo->tx_failed =
6550 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
6551 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
6552 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
6553 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
6554
6555 sinfo->filled |=
6556 STATION_INFO_TX_PACKETS |
6557 STATION_INFO_TX_RETRIES |
6558 STATION_INFO_TX_FAILED;
6559
6560 EXIT();
6561 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006562}
6563
6564static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
6565 struct net_device *dev, bool mode, v_SINT_t timeout)
6566{
6567 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6568 VOS_STATUS vos_status;
6569
Jeff Johnsone7245742012-09-05 17:12:55 -07006570 ENTER();
6571
Jeff Johnson295189b2012-06-20 16:38:30 -07006572 if (NULL == pAdapter)
6573 {
6574 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6575 return -ENODEV;
6576 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006577 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6578 {
6579 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6580 "%s:LOGP in Progress. Ignore!!!", __func__);
6581 return -EAGAIN;
6582 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006583
6584 /**The get power cmd from the supplicant gets updated by the nl only
6585 *on successful execution of the function call
6586 *we are oppositely mapped w.r.t mode in the driver
6587 **/
6588 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
6589
Jeff Johnsone7245742012-09-05 17:12:55 -07006590 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006591 if (VOS_STATUS_E_FAILURE == vos_status)
6592 {
6593 return -EINVAL;
6594 }
6595 return 0;
6596}
6597
6598
6599#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6600static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
6601 struct net_device *netdev,
6602 u8 key_index)
6603{
Jeff Johnsone7245742012-09-05 17:12:55 -07006604 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006605 return 0;
6606}
6607#endif //LINUX_VERSION_CODE
6608
6609#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
6610static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6611 struct net_device *dev,
6612 struct ieee80211_txq_params *params)
6613{
Jeff Johnsone7245742012-09-05 17:12:55 -07006614 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006615 return 0;
6616}
6617#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6618static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6619 struct ieee80211_txq_params *params)
6620{
Jeff Johnsone7245742012-09-05 17:12:55 -07006621 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006622 return 0;
6623}
6624#endif //LINUX_VERSION_CODE
6625
6626static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
6627 struct net_device *dev, u8 *mac)
6628{
6629 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006630 VOS_STATUS vos_status;
6631 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006632
Jeff Johnsone7245742012-09-05 17:12:55 -07006633 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006634 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6635 {
6636 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6637 return -EINVAL;
6638 }
6639
6640 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6641 {
6642 hddLog( LOGE,
6643 "%s: Wlan Load/Unload is in progress", __func__);
6644 return -EBUSY;
6645 }
6646
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006647 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6648 {
6649 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6650 "%s:LOGP in Progress. Ignore!!!", __func__);
6651 return -EAGAIN;
6652 }
6653
Jeff Johnson295189b2012-06-20 16:38:30 -07006654 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006655 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006656 )
6657 {
6658 if( NULL == mac )
6659 {
6660 v_U16_t i;
6661 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
6662 {
6663 if(pAdapter->aStaInfo[i].isUsed)
6664 {
6665 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
6666 hddLog(VOS_TRACE_LEVEL_INFO,
6667 "%s: Delete STA with MAC::"
6668 "%02x:%02x:%02x:%02x:%02x:%02x",
6669 __func__,
6670 macAddr[0], macAddr[1], macAddr[2],
6671 macAddr[3], macAddr[4], macAddr[5]);
6672 hdd_softap_sta_deauth(pAdapter, macAddr);
6673 }
6674 }
6675 }
6676 else
6677 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006678
6679 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
6680 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6681 {
6682 hddLog(VOS_TRACE_LEVEL_INFO,
6683 "%s: Skip this DEL STA as this is not used::"
6684 "%02x:%02x:%02x:%02x:%02x:%02x",
6685 __func__,
6686 mac[0], mac[1], mac[2],
6687 mac[3], mac[4], mac[5]);
6688 return -ENOENT;
6689 }
6690
6691 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
6692 {
6693 hddLog(VOS_TRACE_LEVEL_INFO,
6694 "%s: Skip this DEL STA as deauth is in progress::"
6695 "%02x:%02x:%02x:%02x:%02x:%02x",
6696 __func__,
6697 mac[0], mac[1], mac[2],
6698 mac[3], mac[4], mac[5]);
6699 return -ENOENT;
6700 }
6701
6702 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
6703
Jeff Johnson295189b2012-06-20 16:38:30 -07006704 hddLog(VOS_TRACE_LEVEL_INFO,
6705 "%s: Delete STA with MAC::"
6706 "%02x:%02x:%02x:%02x:%02x:%02x",
6707 __func__,
6708 mac[0], mac[1], mac[2],
6709 mac[3], mac[4], mac[5]);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006710
6711 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
6712 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6713 {
6714 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
6715 hddLog(VOS_TRACE_LEVEL_INFO,
6716 "%s: STA removal failed for ::"
6717 "%02x:%02x:%02x:%02x:%02x:%02x",
6718 __func__,
6719 mac[0], mac[1], mac[2],
6720 mac[3], mac[4], mac[5]);
6721 return -ENOENT;
6722 }
6723
Jeff Johnson295189b2012-06-20 16:38:30 -07006724 }
6725 }
6726
6727 EXIT();
6728
6729 return 0;
6730}
6731
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006732static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
6733 struct net_device *dev, u8 *mac, struct station_parameters *params)
6734{
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006735 int status = -EPERM;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006736#ifdef FEATURE_WLAN_TDLS
6737 u32 mask, set;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006738 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006739 mask = params->sta_flags_mask;
6740
6741 set = params->sta_flags_set;
6742
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006743#ifdef WLAN_FEATURE_TDLS_DEBUG
6744 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6745 "%s: mask 0x%x set 0x%x " MAC_ADDRESS_STR,
6746 __func__, mask, set, MAC_ADDR_ARRAY(mac));
6747#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006748
6749 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6750 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006751 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006752 }
6753 }
6754#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006755 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006756}
6757
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006758
6759#ifdef FEATURE_WLAN_LFR
6760static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006761 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006762{
6763#define MAX_PMKSAIDS_IN_CACHE 8
6764 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -07006765 static tANI_U32 i; // HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006766 tANI_U32 j=0;
6767 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6768 tHalHandle halHandle;
6769 eHalStatus result;
6770 tANI_U8 BSSIDMatched = 0;
6771
Jeff Johnsone7245742012-09-05 17:12:55 -07006772 ENTER();
6773
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006774 // Validate pAdapter
6775 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6776 {
6777 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6778 return -EINVAL;
6779 }
6780
6781 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6782 {
6783 hddLog( LOGE,
6784 "%s: Wlan Load/Unload is in progress", __func__);
6785 return -EBUSY;
6786 }
6787
6788 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6789 {
6790 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6791 "%s:LOGP in Progress. Ignore!!!", __func__);
6792 return -EAGAIN;
6793 }
6794
6795 // Retrieve halHandle
6796 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
6797
6798 for (j = 0; j < i; j++)
6799 {
6800 if(vos_mem_compare(PMKIDCache[j].BSSID,
6801 pmksa->bssid, WNI_CFG_BSSID_LEN))
6802 {
6803 /* BSSID matched previous entry. Overwrite it. */
6804 BSSIDMatched = 1;
6805 vos_mem_copy(PMKIDCache[j].BSSID,
6806 pmksa->bssid, WNI_CFG_BSSID_LEN);
6807 vos_mem_copy(PMKIDCache[j].PMKID,
6808 pmksa->pmkid,
6809 CSR_RSN_PMKID_SIZE);
6810 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006811 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006812 dump_bssid(pmksa->bssid);
6813 dump_pmkid(halHandle, pmksa->pmkid);
6814 break;
6815 }
6816 }
6817
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07006818 /* Check we compared all entries,if then take the first slot now */
6819 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
6820
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006821 if (!BSSIDMatched)
6822 {
6823 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
6824 vos_mem_copy(PMKIDCache[i].BSSID,
6825 pmksa->bssid, ETHER_ADDR_LEN);
6826 vos_mem_copy(PMKIDCache[i].PMKID,
6827 pmksa->pmkid,
6828 CSR_RSN_PMKID_SIZE);
6829 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006830 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006831 dump_bssid(pmksa->bssid);
6832 dump_pmkid(halHandle, pmksa->pmkid);
6833 // Increment the HDD Local Cache index
6834 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
6835 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
6836 }
6837
6838
6839 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
6840 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006841 // __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006842 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006843 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006844 // Finally set the PMKSA ID Cache in CSR
6845 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
6846 PMKIDCache,
6847 i );
6848 return 0;
6849}
6850
6851
6852static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006853 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006854{
Jeff Johnsone7245742012-09-05 17:12:55 -07006855 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006856 // TODO: Implement this later.
6857 return 0;
6858}
6859
6860static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
6861{
Jeff Johnsone7245742012-09-05 17:12:55 -07006862 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006863 // TODO: Implement this later.
6864 return 0;
6865}
6866#endif
6867
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006868#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6869static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
6870 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
6871{
6872 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6873 hdd_station_ctx_t *pHddStaCtx;
6874
6875 if (NULL == pAdapter)
6876 {
6877 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6878 return -ENODEV;
6879 }
6880
6881 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6882
6883 // Added for debug on reception of Re-assoc Req.
6884 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6885 {
6886 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
6887 ftie->ie_len);
6888 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
6889 }
6890
6891#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
6892 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
6893 ftie->ie_len);
6894#endif
6895
6896 // Pass the received FT IEs to SME
Gopichand Nakkala356fb102013-03-06 12:34:04 +05306897 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6898 (const u8 *)ftie->ie,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006899 ftie->ie_len);
6900 return 0;
6901}
6902#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006903
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006904#ifdef FEATURE_WLAN_TDLS
6905static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
6906 u8 *peer, u8 action_code, u8 dialog_token,
6907 u16 status_code, const u8 *buf, size_t len)
6908{
6909
6910 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6911 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006912 u8 peerMac[6];
6913 VOS_STATUS status;
Gopichand Nakkala05922802013-03-14 12:23:19 -07006914 int max_sta_failed = 0;
Hoonki Leea34dd892013-02-05 22:56:02 -08006915 int responder;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006916
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006917 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006918 {
6919 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6920 "Invalid arguments");
6921 return -EINVAL;
6922 }
6923
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006924 if (pHddCtx->isLogpInProgress)
6925 {
6926 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6927 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006928 wlan_hdd_tdls_set_link_status(pAdapter, peer, eTDLS_LINK_IDLE);
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006929 return -EBUSY;
6930 }
6931
Hoonki Lee27511902013-03-14 18:19:06 -07006932 if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006933 {
Hoonki Lee27511902013-03-14 18:19:06 -07006934 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6935 "%s: TDLS mode is disabled OR not enabled in FW."
6936 MAC_ADDRESS_STR " action %d declined.",
6937 __func__, MAC_ADDR_ARRAY(peer), action_code);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006938 return -ENOTSUPP;
6939 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006940
Hoonki Lee27511902013-03-14 18:19:06 -07006941 if ((SIR_MAC_TDLS_SETUP_RSP == action_code) ||
6942 (SIR_MAC_TDLS_DIS_RSP == action_code))
6943 {
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07006944 wlan_hdd_tdls_set_cap (pAdapter, peer, eTDLS_CAP_SUPPORTED);
Hoonki Lee27511902013-03-14 18:19:06 -07006945 }
6946
6947 /* other than teardown frame, other mgmt frames are not sent if disabled */
6948 if (SIR_MAC_TDLS_TEARDOWN != action_code)
6949 {
6950 /* if tdls_mode is disabled to respond to peer's request */
6951 if (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode)
6952 {
6953 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6954 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006955 " TDLS mode is disabled. action %d declined.",
6956 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee27511902013-03-14 18:19:06 -07006957
6958 return -ENOTSUPP;
6959 }
6960 }
6961
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006962 if (WLAN_IS_TDLS_SETUP_ACTION(action_code))
6963 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006964 if (wlan_hdd_tdls_is_progress(pAdapter, peer, TRUE))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006965 {
6966 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006967 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006968 " TDLS setup is ongoing. action %d declined.",
6969 __func__, MAC_ADDR_ARRAY(peer), action_code);
6970 return -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006971 }
6972 }
6973
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006974 if (SIR_MAC_TDLS_SETUP_REQ == action_code ||
6975 SIR_MAC_TDLS_SETUP_RSP == action_code )
Lee Hoonkic1262f22013-01-24 21:59:00 -08006976 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006977 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
Lee Hoonkic1262f22013-01-24 21:59:00 -08006978 {
6979 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
6980 we return error code at 'add_station()'. Hence we have this
6981 check again in addtion to add_station().
6982 Anyway, there is no hard to double-check. */
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006983 if (SIR_MAC_TDLS_SETUP_REQ == action_code)
Lee Hoonkic1262f22013-01-24 21:59:00 -08006984 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006985 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6986 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006987 " TDLS Max peer already connected. action %d declined.",
6988 __func__, MAC_ADDR_ARRAY(peer), action_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006989 goto error;
Lee Hoonkic1262f22013-01-24 21:59:00 -08006990 }
6991 else
6992 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006993 /* maximum reached. tweak to send error code to peer and return
6994 error code to supplicant */
Lee Hoonkic1262f22013-01-24 21:59:00 -08006995 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006996 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6997 "%s: " MAC_ADDRESS_STR
6998 " TDLS Max peer already connected send response status %d",
6999 __func__, MAC_ADDR_ARRAY(peer), status_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07007000 max_sta_failed = -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007001 /* fall through to send setup resp with failure status
7002 code */
Lee Hoonkic1262f22013-01-24 21:59:00 -08007003 }
7004 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007005 else
7006 {
7007 hddTdlsPeer_t *pTdlsPeer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007008 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007009 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007010 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007011 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07007012 "%s:" MAC_ADDRESS_STR " already connected. action %d declined.",
7013 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007014 return -EPERM;
7015 }
7016 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08007017 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007018 vos_mem_copy(peerMac, peer, 6);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007019
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007020#ifdef WLAN_FEATURE_TDLS_DEBUG
7021 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007022 "%s: " MAC_ADDRESS_STR " action %d, dialog_token %d status %d, len = %d",
7023 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
7024 action_code, dialog_token, status_code, len);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007025#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007026
Hoonki Leea34dd892013-02-05 22:56:02 -08007027 /*Except teardown responder will not be used so just make 0*/
7028 responder = 0;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007029 if (SIR_MAC_TDLS_TEARDOWN == action_code)
Hoonki Leea34dd892013-02-05 22:56:02 -08007030 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007031 responder = wlan_hdd_tdls_get_responder(pAdapter, peerMac);
7032 if(-1 == responder)
Hoonki Leea34dd892013-02-05 22:56:02 -08007033 {
7034 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007035 "%s: " MAC_ADDRESS_STR " peer doesn't exist dialog_token %d status %d, len = %d",
7036 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
Hoonki Leea34dd892013-02-05 22:56:02 -08007037 dialog_token, status_code, len);
7038 return -EPERM;
7039 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007040 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007041
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007042 INIT_COMPLETION(pAdapter->tdls_mgmt_comp);
7043
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007044 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
Hoonki Leea34dd892013-02-05 22:56:02 -08007045 peerMac, action_code, dialog_token, status_code, (tANI_U8 *)buf, len, responder);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007046
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007047 if (VOS_STATUS_SUCCESS != status)
7048 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007049 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7050 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07007051 return -EPERM;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007052 }
7053
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08007054 /* not block discovery request, as it is called from timer callback */
7055 if (SIR_MAC_TDLS_DIS_REQ != action_code)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007056 {
Pervinder Singhb4638422013-03-04 22:51:36 -08007057 long rc;
7058
7059 rc = wait_for_completion_interruptible_timeout(&pAdapter->tdls_mgmt_comp,
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08007060 msecs_to_jiffies(WAIT_TIME_TDLS_MGMT));
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007061
Pervinder Singhb4638422013-03-04 22:51:36 -08007062 if ((rc <= 0) || (TRUE != pAdapter->mgmtTxCompletionStatus))
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08007063 {
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08007064 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pervinder Singhb4638422013-03-04 22:51:36 -08007065 "%s: Mgmt Tx Completion failed status %ld TxCompletion %lu",
7066 __func__, rc, pAdapter->mgmtTxCompletionStatus);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07007067 return -EPERM;
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08007068 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007069 }
7070
Gopichand Nakkala05922802013-03-14 12:23:19 -07007071 if (max_sta_failed)
7072 return max_sta_failed;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007073
Hoonki Leea34dd892013-02-05 22:56:02 -08007074 if (SIR_MAC_TDLS_SETUP_RSP == action_code)
7075 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007076 wlan_hdd_tdls_set_responder(pAdapter, peerMac, TRUE);
Hoonki Leea34dd892013-02-05 22:56:02 -08007077 }
7078 else if (SIR_MAC_TDLS_SETUP_CNF == action_code)
7079 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007080 wlan_hdd_tdls_set_responder(pAdapter, peerMac, FALSE);
Hoonki Leea34dd892013-02-05 22:56:02 -08007081 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007082
7083 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07007084error:
7085 /* max_sta_failed ; we didn't set to CONNECTING for this case,
7086 because we already know that this transaction will be failed,
7087 but we weren't sure if supplicant call DISABLE_LINK or not. So,
7088 to be safe, do not change the state mahine.
7089 */
7090 if(max_sta_failed == 0 &&
7091 (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
7092 wlan_hdd_tdls_set_link_status(pAdapter, peerMac, eTDLS_LINK_IDLE);
7093 return -EPERM;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007094}
7095
7096static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
7097 u8 *peer, enum nl80211_tdls_operation oper)
7098{
7099 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7100 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007101#ifdef WLAN_FEATURE_TDLS_DEBUG
7102 const char *tdls_oper_str[]= {
7103 "NL80211_TDLS_DISCOVERY_REQ",
7104 "NL80211_TDLS_SETUP",
7105 "NL80211_TDLS_TEARDOWN",
7106 "NL80211_TDLS_ENABLE_LINK",
7107 "NL80211_TDLS_DISABLE_LINK",
7108 "NL80211_TDLS_UNKONW_OPER"};
7109#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007110
Chilam Ngc4244af2013-04-01 15:37:32 -07007111 if ( NULL == pHddCtx || NULL == pHddCtx->cfg_ini || NULL == peer )
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007112 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007113 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Chilam Ngc4244af2013-04-01 15:37:32 -07007114 "%s: Invalid arguments", __func__);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007115 return -EINVAL;
7116 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007117
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08007118 if (pHddCtx->isLogpInProgress)
7119 {
7120 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7121 "%s:LOGP in Progress. Ignore!!!", __func__);
7122 return -EBUSY;
7123 }
7124
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007125#ifdef WLAN_FEATURE_TDLS_DEBUG
7126 if((int)oper > 4)
7127 oper = 5;
7128
7129 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007130 "%s: " MAC_ADDRESS_STR " %d (%s) ", "tdls_oper",
7131 MAC_ADDR_ARRAY(peer), (int)oper,
7132 tdls_oper_str[(int)oper]);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007133#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007134
7135 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007136 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007137 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007138 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Chilam Ngc4244af2013-04-01 15:37:32 -07007139 "TDLS Disabled in INI OR not enabled in FW. "
7140 "Cannot process TDLS commands");
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007141 return -ENOTSUPP;
7142 }
7143
7144 switch (oper) {
7145 case NL80211_TDLS_ENABLE_LINK:
7146 {
Hoonki Lee387663d2013-02-05 18:08:43 -08007147 hddTdlsPeer_t *pTdlsPeer;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007148 VOS_STATUS status;
7149
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007150 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007151
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007152 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
7153 "%s: TDLS_LINK_ENABLE " MAC_ADDRESS_STR,
7154 __func__, MAC_ADDR_ARRAY(peer));
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007155
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007156 if ( NULL == pTdlsPeer ) {
7157 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_hdd_tdls_find_peer "
7158 MAC_ADDRESS_STR " failed",
7159 __func__, MAC_ADDR_ARRAY(peer));
7160 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007161 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007162
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007163 if (eTDLS_LINK_CONNECTING == pTdlsPeer->link_status)
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007164 {
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007165 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007166 /* start TDLS client registration with TL */
7167 status = hdd_roamRegisterTDLSSTA( pAdapter, peer, pTdlsPeer->staId, pTdlsPeer->signature);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007168 if (VOS_STATUS_SUCCESS == status)
7169 {
7170 wlan_hdd_tdls_increment_peer_count(pAdapter);
7171 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007172 wlan_hdd_tdls_check_bmps(pAdapter);
7173 }
7174
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007175 }
7176 break;
7177 case NL80211_TDLS_DISABLE_LINK:
Lee Hoonkic1262f22013-01-24 21:59:00 -08007178 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007179 hddTdlsPeer_t *curr_peer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007180
7181 if(NULL != curr_peer)
Lee Hoonkic1262f22013-01-24 21:59:00 -08007182 {
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007183 long status;
7184
7185 INIT_COMPLETION(pAdapter->tdls_del_station_comp);
7186
Lee Hoonkic1262f22013-01-24 21:59:00 -08007187 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
7188 pAdapter->sessionId, peer );
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007189
7190 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_del_station_comp,
7191 msecs_to_jiffies(WAIT_TIME_TDLS_DEL_STA));
7192 if (status <= 0)
7193 {
7194 wlan_hdd_tdls_set_peer_link_status(curr_peer, eTDLS_LINK_IDLE);
7195 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7196 "%s: Del station failed status %ld",
7197 __func__, status);
7198 return -EPERM;
7199 }
Gopichand Nakkala8b00c632013-03-08 19:47:52 -08007200 wlan_hdd_tdls_set_peer_link_status(curr_peer, eTDLS_LINK_IDLE);
Lee Hoonkic1262f22013-01-24 21:59:00 -08007201 }
7202 else
7203 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007204 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7205 "%s: TDLS Peer Station doesn't exist.", __func__);
Lee Hoonkic1262f22013-01-24 21:59:00 -08007206 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08007207 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007208 break;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007209 case NL80211_TDLS_TEARDOWN:
7210 case NL80211_TDLS_SETUP:
7211 case NL80211_TDLS_DISCOVERY_REQ:
7212 /* We don't support in-driver setup/teardown/discovery */
7213 return -ENOTSUPP;
7214 default:
7215 return -ENOTSUPP;
7216 }
7217 return 0;
7218}
Chilam NG571c65a2013-01-19 12:27:36 +05307219
7220int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
7221 struct net_device *dev, u8 *peer)
7222{
7223 hddLog(VOS_TRACE_LEVEL_INFO, "tdls send discover req: %x %x %x %x %x %x",
7224 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5]);
7225
7226 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
7227 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
7228}
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007229#endif
7230
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05307231#ifdef WLAN_FEATURE_GTK_OFFLOAD
7232/*
7233 * FUNCTION: wlan_hdd_cfg80211_update_replayCounterCallback
7234 * Callback rountine called upon receiving response for
7235 * get offload info
7236 */
7237void wlan_hdd_cfg80211_update_replayCounterCallback(void *callbackContext,
7238 tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoRsp)
7239{
7240
7241 hdd_adapter_t *pAdapter = (hdd_adapter_t *)callbackContext;
7242
7243 ENTER();
7244
7245 if (NULL == pAdapter)
7246 {
7247 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7248 "%s: HDD adapter is Null", __func__);
7249 return ;
7250 }
7251
7252 if (NULL == pGtkOffloadGetInfoRsp)
7253 {
7254 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7255 "%s: pGtkOffloadGetInfoRsp is Null", __func__);
7256 return ;
7257 }
7258
7259 if (VOS_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus)
7260 {
7261 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7262 "%s: wlan Failed to get replay counter value",
7263 __func__);
7264 return ;
7265 }
7266
7267 /* Update replay counter to NL */
7268 cfg80211_gtk_rekey_notify(pAdapter->dev, pGtkOffloadGetInfoRsp->bssId,
7269 (tANI_U8 *)&pGtkOffloadGetInfoRsp->ullKeyReplayCounter, GFP_KERNEL);
7270}
7271
7272/*
7273 * FUNCTION: wlan_hdd_cfg80211_set_rekey_data
7274 * This function is used to offload GTK rekeying job to the firmware.
7275 */
7276int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
7277 struct cfg80211_gtk_rekey_data *data)
7278{
7279 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7280 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
7281 hdd_station_ctx_t *pHddStaCtx;
7282 tHalHandle hHal;
7283 tpSirGtkOffloadParams pGtkOffloadReqParams;
7284 eHalStatus status = eHAL_STATUS_FAILURE;
7285
7286 ENTER();
7287
7288 if (NULL == pAdapter)
7289 {
7290 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7291 "%s: HDD adapter is Null", __func__);
7292 return -ENODEV;
7293 }
7294
7295 if (NULL == pHddCtx)
7296 {
7297 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7298 "%s: HDD context is Null!!!", __func__);
7299 return -ENODEV;
7300 }
7301
7302 if (pHddCtx->isLogpInProgress)
7303 {
7304 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7305 "%s: LOGP in Progress. Ignore!!!", __func__);
7306 return -EAGAIN;
7307 }
7308
7309 if (pHddCtx->isLoadUnloadInProgress)
7310 {
7311 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7312 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
7313 return -EAGAIN;
7314 }
7315
7316 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7317 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
7318 if (NULL == hHal)
7319 {
7320 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7321 "%s: HAL context is Null!!!", __func__);
7322 return -EAGAIN;
7323 }
7324
7325 pGtkOffloadReqParams =
7326 &pHddStaCtx->gtkOffloadRequestParams.gtkOffloadReqParams;
7327
7328 pGtkOffloadReqParams->ulFlags = GTK_OFFLOAD_ENABLE;
7329 memcpy(pGtkOffloadReqParams->aKCK, data->kck, NL80211_KCK_LEN);
7330 memcpy(pGtkOffloadReqParams->aKEK, data->kek, NL80211_KEK_LEN);
7331 memcpy(pGtkOffloadReqParams->bssId, &pHddStaCtx->conn_info.bssId,
7332 WNI_CFG_BSSID_LEN);
7333 memcpy(&pGtkOffloadReqParams->ullKeyReplayCounter, &data->replay_ctr,
7334 sizeof (tANI_U64));
7335
7336 if (TRUE == pHddCtx->hdd_wlan_suspended)
7337 {
7338 /* if wlan is suspended, enable GTK offload directly from here */
7339 status = sme_SetGTKOffload(hHal, pGtkOffloadReqParams,
7340 pAdapter->sessionId);
7341
7342 if (eHAL_STATUS_SUCCESS != status)
7343 {
7344 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7345 "%s: sme_SetGTKOffload failed, returned %d",
7346 __func__, status);
7347 return status;
7348 }
7349 pHddStaCtx->gtkOffloadRequestParams.requested = FALSE;
7350 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7351 "%s: sme_SetGTKOffload successfull", __func__);
7352 }
7353 else
7354 {
7355 pHddStaCtx->gtkOffloadRequestParams.requested = TRUE;
7356 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7357 "%s: wlan not suspended GTKOffload request is stored",
7358 __func__);
7359 return eHAL_STATUS_SUCCESS;
7360 }
7361 return status;
7362}
7363#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
7364
Jeff Johnson295189b2012-06-20 16:38:30 -07007365/* cfg80211_ops */
7366static struct cfg80211_ops wlan_hdd_cfg80211_ops =
7367{
7368 .add_virtual_intf = wlan_hdd_add_virtual_intf,
7369 .del_virtual_intf = wlan_hdd_del_virtual_intf,
7370 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
7371 .change_station = wlan_hdd_change_station,
7372#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
7373 .add_beacon = wlan_hdd_cfg80211_add_beacon,
7374 .del_beacon = wlan_hdd_cfg80211_del_beacon,
7375 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007376#else
7377 .start_ap = wlan_hdd_cfg80211_start_ap,
7378 .change_beacon = wlan_hdd_cfg80211_change_beacon,
7379 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07007380#endif
7381 .change_bss = wlan_hdd_cfg80211_change_bss,
7382 .add_key = wlan_hdd_cfg80211_add_key,
7383 .get_key = wlan_hdd_cfg80211_get_key,
7384 .del_key = wlan_hdd_cfg80211_del_key,
7385 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08007386#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07007387 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08007388#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007389 .scan = wlan_hdd_cfg80211_scan,
7390 .connect = wlan_hdd_cfg80211_connect,
7391 .disconnect = wlan_hdd_cfg80211_disconnect,
7392 .join_ibss = wlan_hdd_cfg80211_join_ibss,
7393 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
7394 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
7395 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
7396 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
Jeff Johnson295189b2012-06-20 16:38:30 -07007397 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
7398 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
7399 .mgmt_tx = wlan_hdd_action,
7400#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7401 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
7402 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
7403 .set_txq_params = wlan_hdd_set_txq_params,
7404#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007405 .get_station = wlan_hdd_cfg80211_get_station,
7406 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
7407 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007408 .add_station = wlan_hdd_cfg80211_add_station,
7409#ifdef FEATURE_WLAN_LFR
7410 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
7411 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
7412 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
7413#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007414#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
7415 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
7416#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007417#ifdef FEATURE_WLAN_TDLS
7418 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
7419 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
7420#endif
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05307421#ifdef WLAN_FEATURE_GTK_OFFLOAD
7422 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
7423#endif /* WLAN_FEATURE_GTK_OFFLOAD */
Jeff Johnson295189b2012-06-20 16:38:30 -07007424};
7425