blob: 62e3c0c5324b88883bfdee5e5055eac505264e15 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/**========================================================================
43
44 \file wlan_hdd_cfg80211.c
45
46 \brief WLAN Host Device Driver implementation
47
48 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
49
50 Qualcomm Confidential and Proprietary.
51
52 ========================================================================*/
53
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070054/**=========================================================================
Jeff Johnson295189b2012-06-20 16:38:30 -070055
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070056 EDIT HISTORY FOR FILE
Jeff Johnson295189b2012-06-20 16:38:30 -070057
58
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070059 This section contains comments describing changes made to the module.
60 Notice that changes are listed in reverse chronological order.
Jeff Johnson295189b2012-06-20 16:38:30 -070061
62
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070063 $Header:$ $DateTime: $ $Author: $
Jeff Johnson295189b2012-06-20 16:38:30 -070064
65
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070066 when who what, where, why
Jeff Johnson295189b2012-06-20 16:38:30 -070067 -------- --- --------------------------------------------------------
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070068 21/12/09 Ashwani Created module.
Jeff Johnson295189b2012-06-20 16:38:30 -070069
70 07/06/10 Kumar Deepak Implemented cfg80211 callbacks for ANDROID
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070071 Ganesh K
Jeff Johnson295189b2012-06-20 16:38:30 -070072 ==========================================================================*/
73
Jeff Johnson295189b2012-06-20 16:38:30 -070074
75#include <linux/version.h>
76#include <linux/module.h>
77#include <linux/kernel.h>
78#include <linux/init.h>
79#include <linux/wireless.h>
80#include <wlan_hdd_includes.h>
81#include <net/arp.h>
82#include <net/cfg80211.h>
83#include <linux/wireless.h>
84#include <wlan_hdd_wowl.h>
85#include <aniGlobal.h>
86#include "ccmApi.h"
87#include "sirParams.h"
88#include "dot11f.h"
89#include "wlan_hdd_assoc.h"
90#include "wlan_hdd_wext.h"
91#include "sme_Api.h"
92#include "wlan_hdd_p2p.h"
93#include "wlan_hdd_cfg80211.h"
94#include "wlan_hdd_hostapd.h"
95#include "sapInternal.h"
96#include "wlan_hdd_softap_tx_rx.h"
97#include "wlan_hdd_main.h"
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +053098#include "wlan_hdd_assoc.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070099#ifdef WLAN_BTAMP_FEATURE
100#include "bap_hdd_misc.h"
101#endif
102#include <qc_sap_ioctl.h>
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800103#ifdef FEATURE_WLAN_TDLS
104#include "wlan_hdd_tdls.h"
105#endif
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +0530106#include "wlan_nv.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700107
108#define g_mode_rates_size (12)
109#define a_mode_rates_size (8)
110#define FREQ_BASE_80211G (2407)
111#define FREQ_BAND_DIFF_80211G (5)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700112#define MAX_SCAN_SSID 9
Jeff Johnson295189b2012-06-20 16:38:30 -0700113#define GET_IE_LEN_IN_BSS_DESC(lenInBss) ( lenInBss + sizeof(lenInBss) - \
114 ((int) OFFSET_OF( tSirBssDescription, ieFields)))
115
116#define HDD2GHZCHAN(freq, chan, flag) { \
117 .band = IEEE80211_BAND_2GHZ, \
118 .center_freq = (freq), \
119 .hw_value = (chan),\
120 .flags = (flag), \
121 .max_antenna_gain = 0 ,\
122 .max_power = 30, \
123}
124
125#define HDD5GHZCHAN(freq, chan, flag) { \
126 .band = IEEE80211_BAND_5GHZ, \
127 .center_freq = (freq), \
128 .hw_value = (chan),\
129 .flags = (flag), \
130 .max_antenna_gain = 0 ,\
131 .max_power = 30, \
132}
133
134#define HDD_G_MODE_RATETAB(rate, rate_id, flag)\
135{\
136 .bitrate = rate, \
137 .hw_value = rate_id, \
138 .flags = flag, \
139}
140
Lee Hoonkic1262f22013-01-24 21:59:00 -0800141#ifndef WLAN_FEATURE_TDLS_DEBUG
142#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_INFO
143#else
144#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_ERROR
145#endif
146
Gopichand Nakkala356fb102013-03-06 12:34:04 +0530147#ifdef WLAN_FEATURE_VOWIFI_11R
148#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
149#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
150#endif
151
Jeff Johnson295189b2012-06-20 16:38:30 -0700152static const u32 hdd_cipher_suites[] =
153{
154 WLAN_CIPHER_SUITE_WEP40,
155 WLAN_CIPHER_SUITE_WEP104,
156 WLAN_CIPHER_SUITE_TKIP,
157#ifdef FEATURE_WLAN_CCX
158#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
159 WLAN_CIPHER_SUITE_KRK,
160 WLAN_CIPHER_SUITE_CCMP,
161#else
162 WLAN_CIPHER_SUITE_CCMP,
163#endif
164#ifdef FEATURE_WLAN_WAPI
165 WLAN_CIPHER_SUITE_SMS4,
166#endif
Chet Lanctot186b5732013-03-18 10:26:30 -0700167#ifdef WLAN_FEATURE_11W
168 WLAN_CIPHER_SUITE_AES_CMAC,
169#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700170};
171
172static inline int is_broadcast_ether_addr(const u8 *addr)
173{
174 return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&
175 (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
176}
177
178static struct ieee80211_channel hdd_channels_2_4_GHZ[] =
179{
180 HDD2GHZCHAN(2412, 1, 0) ,
181 HDD2GHZCHAN(2417, 2, 0) ,
182 HDD2GHZCHAN(2422, 3, 0) ,
183 HDD2GHZCHAN(2427, 4, 0) ,
184 HDD2GHZCHAN(2432, 5, 0) ,
185 HDD2GHZCHAN(2437, 6, 0) ,
186 HDD2GHZCHAN(2442, 7, 0) ,
187 HDD2GHZCHAN(2447, 8, 0) ,
188 HDD2GHZCHAN(2452, 9, 0) ,
189 HDD2GHZCHAN(2457, 10, 0) ,
190 HDD2GHZCHAN(2462, 11, 0) ,
191 HDD2GHZCHAN(2467, 12, 0) ,
192 HDD2GHZCHAN(2472, 13, 0) ,
193 HDD2GHZCHAN(2484, 14, 0) ,
194};
195
Jeff Johnson295189b2012-06-20 16:38:30 -0700196static struct ieee80211_channel hdd_social_channels_2_4_GHZ[] =
197{
198 HDD2GHZCHAN(2412, 1, 0) ,
199 HDD2GHZCHAN(2437, 6, 0) ,
200 HDD2GHZCHAN(2462, 11, 0) ,
201};
Jeff Johnson295189b2012-06-20 16:38:30 -0700202
203static struct ieee80211_channel hdd_channels_5_GHZ[] =
204{
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700205 HDD5GHZCHAN(4920, 240, 0) ,
206 HDD5GHZCHAN(4940, 244, 0) ,
207 HDD5GHZCHAN(4960, 248, 0) ,
208 HDD5GHZCHAN(4980, 252, 0) ,
209 HDD5GHZCHAN(5040, 208, 0) ,
210 HDD5GHZCHAN(5060, 212, 0) ,
211 HDD5GHZCHAN(5080, 216, 0) ,
Jeff Johnson295189b2012-06-20 16:38:30 -0700212 HDD5GHZCHAN(5180, 36, 0) ,
213 HDD5GHZCHAN(5200, 40, 0) ,
214 HDD5GHZCHAN(5220, 44, 0) ,
215 HDD5GHZCHAN(5240, 48, 0) ,
216 HDD5GHZCHAN(5260, 52, 0) ,
217 HDD5GHZCHAN(5280, 56, 0) ,
218 HDD5GHZCHAN(5300, 60, 0) ,
219 HDD5GHZCHAN(5320, 64, 0) ,
220 HDD5GHZCHAN(5500,100, 0) ,
221 HDD5GHZCHAN(5520,104, 0) ,
222 HDD5GHZCHAN(5540,108, 0) ,
223 HDD5GHZCHAN(5560,112, 0) ,
224 HDD5GHZCHAN(5580,116, 0) ,
225 HDD5GHZCHAN(5600,120, 0) ,
226 HDD5GHZCHAN(5620,124, 0) ,
227 HDD5GHZCHAN(5640,128, 0) ,
228 HDD5GHZCHAN(5660,132, 0) ,
229 HDD5GHZCHAN(5680,136, 0) ,
230 HDD5GHZCHAN(5700,140, 0) ,
231 HDD5GHZCHAN(5745,149, 0) ,
232 HDD5GHZCHAN(5765,153, 0) ,
233 HDD5GHZCHAN(5785,157, 0) ,
234 HDD5GHZCHAN(5805,161, 0) ,
235 HDD5GHZCHAN(5825,165, 0) ,
236};
237
238static struct ieee80211_rate g_mode_rates[] =
239{
240 HDD_G_MODE_RATETAB(10, 0x1, 0),
241 HDD_G_MODE_RATETAB(20, 0x2, 0),
242 HDD_G_MODE_RATETAB(55, 0x4, 0),
243 HDD_G_MODE_RATETAB(110, 0x8, 0),
244 HDD_G_MODE_RATETAB(60, 0x10, 0),
245 HDD_G_MODE_RATETAB(90, 0x20, 0),
246 HDD_G_MODE_RATETAB(120, 0x40, 0),
247 HDD_G_MODE_RATETAB(180, 0x80, 0),
248 HDD_G_MODE_RATETAB(240, 0x100, 0),
249 HDD_G_MODE_RATETAB(360, 0x200, 0),
250 HDD_G_MODE_RATETAB(480, 0x400, 0),
251 HDD_G_MODE_RATETAB(540, 0x800, 0),
252};
253
254static struct ieee80211_rate a_mode_rates[] =
255{
256 HDD_G_MODE_RATETAB(60, 0x10, 0),
257 HDD_G_MODE_RATETAB(90, 0x20, 0),
258 HDD_G_MODE_RATETAB(120, 0x40, 0),
259 HDD_G_MODE_RATETAB(180, 0x80, 0),
260 HDD_G_MODE_RATETAB(240, 0x100, 0),
261 HDD_G_MODE_RATETAB(360, 0x200, 0),
262 HDD_G_MODE_RATETAB(480, 0x400, 0),
263 HDD_G_MODE_RATETAB(540, 0x800, 0),
264};
265
266static struct ieee80211_supported_band wlan_hdd_band_2_4_GHZ =
267{
268 .channels = hdd_channels_2_4_GHZ,
269 .n_channels = ARRAY_SIZE(hdd_channels_2_4_GHZ),
270 .band = IEEE80211_BAND_2GHZ,
271 .bitrates = g_mode_rates,
272 .n_bitrates = g_mode_rates_size,
273 .ht_cap.ht_supported = 1,
274 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
275 | IEEE80211_HT_CAP_GRN_FLD
276 | IEEE80211_HT_CAP_DSSSCCK40
277 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
278 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
279 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
280 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
281 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
282 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
283};
284
Jeff Johnson295189b2012-06-20 16:38:30 -0700285static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_GHZ =
286{
287 .channels = hdd_social_channels_2_4_GHZ,
288 .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_GHZ),
289 .band = IEEE80211_BAND_2GHZ,
290 .bitrates = g_mode_rates,
291 .n_bitrates = g_mode_rates_size,
292 .ht_cap.ht_supported = 1,
293 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
294 | IEEE80211_HT_CAP_GRN_FLD
295 | IEEE80211_HT_CAP_DSSSCCK40
296 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
297 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
298 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
299 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
300 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
301 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
302};
Jeff Johnson295189b2012-06-20 16:38:30 -0700303
304static struct ieee80211_supported_band wlan_hdd_band_5_GHZ =
305{
306 .channels = hdd_channels_5_GHZ,
307 .n_channels = ARRAY_SIZE(hdd_channels_5_GHZ),
308 .band = IEEE80211_BAND_5GHZ,
309 .bitrates = a_mode_rates,
310 .n_bitrates = a_mode_rates_size,
311 .ht_cap.ht_supported = 1,
312 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
313 | IEEE80211_HT_CAP_GRN_FLD
314 | IEEE80211_HT_CAP_DSSSCCK40
315 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
316 | IEEE80211_HT_CAP_SGI_40
317 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
318 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
319 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
320 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
321 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
322 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
323};
324
325/* This structure contain information what kind of frame are expected in
326 TX/RX direction for each kind of interface */
327static const struct ieee80211_txrx_stypes
328wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
329 [NL80211_IFTYPE_STATION] = {
330 .tx = 0xffff,
331 .rx = BIT(SIR_MAC_MGMT_ACTION) |
332 BIT(SIR_MAC_MGMT_PROBE_REQ),
333 },
334 [NL80211_IFTYPE_AP] = {
335 .tx = 0xffff,
336 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
337 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
338 BIT(SIR_MAC_MGMT_PROBE_REQ) |
339 BIT(SIR_MAC_MGMT_DISASSOC) |
340 BIT(SIR_MAC_MGMT_AUTH) |
341 BIT(SIR_MAC_MGMT_DEAUTH) |
342 BIT(SIR_MAC_MGMT_ACTION),
343 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700344 [NL80211_IFTYPE_P2P_CLIENT] = {
345 .tx = 0xffff,
346 .rx = BIT(SIR_MAC_MGMT_ACTION) |
347 BIT(SIR_MAC_MGMT_PROBE_REQ),
348 },
349 [NL80211_IFTYPE_P2P_GO] = {
350 /* This is also same as for SoftAP */
351 .tx = 0xffff,
352 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
353 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
354 BIT(SIR_MAC_MGMT_PROBE_REQ) |
355 BIT(SIR_MAC_MGMT_DISASSOC) |
356 BIT(SIR_MAC_MGMT_AUTH) |
357 BIT(SIR_MAC_MGMT_DEAUTH) |
358 BIT(SIR_MAC_MGMT_ACTION),
359 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700360};
361
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800362#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800363static const struct ieee80211_iface_limit
364wlan_hdd_iface_limit[] = {
365 {
Sunil Ravia72c3992013-01-31 06:12:22 -0800366 /* max = 3 ; Our driver create two interfaces during driver init
367 * wlan0 and p2p0 interfaces. p2p0 is considered as station
368 * interface until a group is formed. In JB architecture, once the
369 * group is formed, interface type of p2p0 is changed to P2P GO or
370 * Client.
371 * When supplicant remove the group, it first issue a set interface
372 * cmd to change the mode back to Station. In JB this works fine as
373 * we advertize two station type interface during driver init.
374 * Some vendors create separate interface for P2P GO/Client,
375 * after group formation(Third one). But while group remove
376 * supplicant first tries to change the mode(3rd interface) to STATION
377 * But as we advertized only two sta type interfaces nl80211 was
378 * returning error for the third one which was leading to failure in
379 * delete interface. Ideally while removing the group, supplicant
380 * should not try to change the 3rd interface mode to Station type.
381 * Till we get a fix in wpa_supplicant, we advertize max STA
382 * interface type to 3
383 */
384 .max = 3,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800385 .types = BIT(NL80211_IFTYPE_STATION),
386 },
387 {
388 .max = 1,
389 .types = BIT(NL80211_IFTYPE_AP),
390 },
391 {
392 .max = 1,
393 .types = BIT(NL80211_IFTYPE_P2P_GO) |
394 BIT(NL80211_IFTYPE_P2P_CLIENT),
395 },
396};
397
398/* By default, only single channel concurrency is allowed */
399static struct ieee80211_iface_combination
400wlan_hdd_iface_combination = {
401 .limits = wlan_hdd_iface_limit,
402 .num_different_channels = 1,
Sunil Ravia72c3992013-01-31 06:12:22 -0800403 /*
404 * max = WLAN_MAX_INTERFACES ; JellyBean architecture creates wlan0
405 * and p2p0 interfaces during driver init
406 * Some vendors create separate interface for P2P operations.
407 * wlan0: STA interface
408 * p2p0: P2P Device interface, action frames goes
409 * through this interface.
410 * p2p-xx: P2P interface, After GO negotiation this interface is
411 * created for p2p operations(GO/CLIENT interface).
412 */
413 .max_interfaces = WLAN_MAX_INTERFACES,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800414 .n_limits = ARRAY_SIZE(wlan_hdd_iface_limit),
415 .beacon_int_infra_match = false,
416};
417#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800418
Jeff Johnson295189b2012-06-20 16:38:30 -0700419static struct cfg80211_ops wlan_hdd_cfg80211_ops;
420
421/* Data rate 100KBPS based on IE Index */
422struct index_data_rate_type
423{
424 v_U8_t beacon_rate_index;
425 v_U16_t supported_rate[4];
426};
427
428/* 11B, 11G Rate table include Basic rate and Extended rate
429 The IDX field is the rate index
430 The HI field is the rate when RSSI is strong or being ignored
431 (in this case we report actual rate)
432 The MID field is the rate when RSSI is moderate
433 (in this case we cap 11b rates at 5.5 and 11g rates at 24)
434 The LO field is the rate when RSSI is low
435 (in this case we don't report rates, actual current rate used)
436 */
437static const struct
438{
439 v_U8_t beacon_rate_index;
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700440 v_U16_t supported_rate[4];
Jeff Johnson295189b2012-06-20 16:38:30 -0700441} supported_data_rate[] =
442{
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700443/* IDX HI HM LM LO (RSSI-based index */
444 {2, { 10, 10, 10, 0}},
445 {4, { 20, 20, 10, 0}},
446 {11, { 55, 20, 10, 0}},
447 {12, { 60, 55, 20, 0}},
448 {18, { 90, 55, 20, 0}},
449 {22, {110, 55, 20, 0}},
450 {24, {120, 90, 60, 0}},
451 {36, {180, 120, 60, 0}},
452 {44, {220, 180, 60, 0}},
453 {48, {240, 180, 90, 0}},
454 {66, {330, 180, 90, 0}},
455 {72, {360, 240, 90, 0}},
456 {96, {480, 240, 120, 0}},
457 {108, {540, 240, 120, 0}}
Jeff Johnson295189b2012-06-20 16:38:30 -0700458};
459
460/* MCS Based rate table */
461static struct index_data_rate_type supported_mcs_rate[] =
462{
463/* MCS L20 L40 S20 S40 */
464 {0, {65, 135, 72, 150}},
465 {1, {130, 270, 144, 300}},
466 {2, {195, 405, 217, 450}},
467 {3, {260, 540, 289, 600}},
468 {4, {390, 810, 433, 900}},
469 {5, {520, 1080, 578, 1200}},
470 {6, {585, 1215, 650, 1350}},
471 {7, {650, 1350, 722, 1500}}
472};
473
474extern struct net_device_ops net_ops_struct;
475
476/*
477 * FUNCTION: wlan_hdd_cfg80211_init
478 * This function is called by hdd_wlan_startup()
479 * during initialization.
480 * This function is used to initialize and register wiphy structure.
481 */
482struct wiphy *wlan_hdd_cfg80211_init(int priv_size)
483{
484 struct wiphy *wiphy;
485 ENTER();
486
487 /*
488 * Create wiphy device
489 */
490 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
491
492 if (!wiphy)
493 {
494 /* Print error and jump into err label and free the memory */
495 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__);
496 return NULL;
497 }
498
499 return wiphy;
500}
501
502/*
503 * FUNCTION: wlan_hdd_cfg80211_update_band
504 * This function is called from the supplicant through a
505 * private ioctl to change the band value
506 */
507int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
508{
Jeff Johnsone7245742012-09-05 17:12:55 -0700509 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700510 switch(eBand)
511 {
512 case eCSR_BAND_24:
513 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
514 wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
515 break;
516 case eCSR_BAND_5G:
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700517 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700518 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
519 break;
520 case eCSR_BAND_ALL:
521 default:
522 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
523 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
524 }
525 return 0;
526}
527/*
528 * FUNCTION: wlan_hdd_cfg80211_init
529 * This function is called by hdd_wlan_startup()
530 * during initialization.
531 * This function is used to initialize and register wiphy structure.
532 */
533int wlan_hdd_cfg80211_register(struct device *dev,
534 struct wiphy *wiphy,
535 hdd_config_t *pCfg
536 )
537{
Jeff Johnsone7245742012-09-05 17:12:55 -0700538 ENTER();
539
Jeff Johnson295189b2012-06-20 16:38:30 -0700540 /* Now bind the underlying wlan device with wiphy */
541 set_wiphy_dev(wiphy, dev);
542
543 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
544
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700545 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700546
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700547#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700548 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
549 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
550 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
Jeff Johnsone7245742012-09-05 17:12:55 -0700551 | WIPHY_FLAG_OFFCHAN_TX;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700552#endif
Srinivas Girigowda640728a2013-03-28 12:21:54 -0700553#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
554 if (pCfg->isFastTransitionEnabled
James Zmuda77fb5ae2013-01-29 08:00:17 -0800555#ifdef FEATURE_WLAN_LFR
Srinivas Girigowda640728a2013-03-28 12:21:54 -0700556 || pCfg->isFastRoamIniFeatureEnabled
557#endif
558#ifdef FEATURE_WLAN_CCX
559 || pCfg->isCcxIniFeatureEnabled
560#endif
561 )
562 {
563 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
564 }
James Zmuda77fb5ae2013-01-29 08:00:17 -0800565#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800566#ifdef FEATURE_WLAN_TDLS
567 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
568 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
569#endif
570
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700571 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
572 driver can still register regulatory callback and
573 it will get CRDA setting in wiphy->band[], but
574 driver need to determine what to do with both
575 regulatory settings */
576 wiphy->reg_notifier = wlan_hdd_crda_reg_notifier;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700577
Jeff Johnson295189b2012-06-20 16:38:30 -0700578 wiphy->max_scan_ssids = MAX_SCAN_SSID;
579
580 wiphy->max_scan_ie_len = 200 ; //TODO: define a macro
581
582 /* Supports STATION & AD-HOC modes right now */
583 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
584 | BIT(NL80211_IFTYPE_ADHOC)
Jeff Johnson295189b2012-06-20 16:38:30 -0700585 | BIT(NL80211_IFTYPE_P2P_CLIENT)
586 | BIT(NL80211_IFTYPE_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -0700587 | BIT(NL80211_IFTYPE_AP);
588
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800589#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800590 if( pCfg->enableMCC )
591 {
592 /* Currently, supports up to two channels */
593 wlan_hdd_iface_combination.num_different_channels = 2;
594
595 if( !pCfg->allowMCCGODiffBI )
596 wlan_hdd_iface_combination.beacon_int_infra_match = true;
597
598 }
599 wiphy->iface_combinations = &wlan_hdd_iface_combination;
600 wiphy->n_iface_combinations = 1;
601#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800602
Jeff Johnson295189b2012-06-20 16:38:30 -0700603 /* Before registering we need to update the ht capabilitied based
604 * on ini values*/
605 if( !pCfg->ShortGI20MhzEnable )
606 {
607 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
608 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
609 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
610 }
611
612 if( !pCfg->ShortGI40MhzEnable )
613 {
614 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
615 }
616
617 if( !pCfg->nChannelBondingMode5GHz )
618 {
619 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
620 }
621
622 /*Initialize band capability*/
623 switch(pCfg->nBandCapability)
624 {
625 case eCSR_BAND_24:
626 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
627 break;
628 case eCSR_BAND_5G:
Jeff Johnson295189b2012-06-20 16:38:30 -0700629 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700630 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
631 break;
632 case eCSR_BAND_ALL:
633 default:
634 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
635 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
636 }
637 /*Initialise the supported cipher suite details*/
638 wiphy->cipher_suites = hdd_cipher_suites;
639 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
640
641 /*signal strength in mBm (100*dBm) */
642 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
643
644#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -0700645 wiphy->max_remain_on_channel_duration = 1000;
646#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700647
648 /* Register our wiphy dev with cfg80211 */
649 if (0 > wiphy_register(wiphy))
650 {
651 /* print eror */
652 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
653 return -EIO;
654 }
655
656 EXIT();
657 return 0;
658}
659
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700660/* In this function we will try to get default country code from crda.
661 If the gCrdaDefaultCountryCode is configured in ini file,
662 we will try to call user space crda to get the regulatory settings for
663 that country. We will timeout if we can't get it from crda.
664 It's called by hdd_wlan_startup() after wlan_hdd_cfg80211_register.
665*/
666int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg)
667{
668 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
669 if (memcmp(pCfg->crdaDefaultCountryCode,
670 CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) != 0)
671 {
672 init_completion(&pHddCtx->driver_crda_req);
673 regulatory_hint(wiphy, pCfg->crdaDefaultCountryCode);
674 wait_for_completion_interruptible_timeout(&pHddCtx->driver_crda_req,
675 CRDA_WAIT_TIME);
676 }
677 return 0;
678}
679
Jeff Johnson295189b2012-06-20 16:38:30 -0700680/* In this function we will do all post VOS start initialization.
681 In this function we will register for all frame in which supplicant
682 is interested.
683*/
684void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
685{
Jeff Johnson295189b2012-06-20 16:38:30 -0700686 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
687 /* Register for all P2P action, public action etc frames */
688 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
689
Jeff Johnsone7245742012-09-05 17:12:55 -0700690 ENTER();
691
Jeff Johnson295189b2012-06-20 16:38:30 -0700692 /* Right now we are registering these frame when driver is getting
693 initialized. Once we will move to 2.6.37 kernel, in which we have
694 frame register ops, we will move this code as a part of that */
695 /* GAS Initial Request */
696 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
697 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
698
699 /* GAS Initial Response */
700 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
701 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
702
703 /* GAS Comeback Request */
704 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
705 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
706
707 /* GAS Comeback Response */
708 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
709 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
710
711 /* P2P Public Action */
712 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
713 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
714 P2P_PUBLIC_ACTION_FRAME_SIZE );
715
716 /* P2P Action */
717 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
718 (v_U8_t*)P2P_ACTION_FRAME,
719 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -0700720
721#ifdef WLAN_FEATURE_11W
722 /* SA Query Response Action Frame */
723 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
724 (v_U8_t*)SA_QUERY_FRAME_RSP,
725 SA_QUERY_FRAME_RSP_SIZE );
726#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -0700727}
728
729void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
730{
Jeff Johnson295189b2012-06-20 16:38:30 -0700731 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
732 /* Register for all P2P action, public action etc frames */
733 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
734
Jeff Johnsone7245742012-09-05 17:12:55 -0700735 ENTER();
736
Jeff Johnson295189b2012-06-20 16:38:30 -0700737 /* Right now we are registering these frame when driver is getting
738 initialized. Once we will move to 2.6.37 kernel, in which we have
739 frame register ops, we will move this code as a part of that */
740 /* GAS Initial Request */
741
742 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
743 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
744
745 /* GAS Initial Response */
746 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
747 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
748
749 /* GAS Comeback Request */
750 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
751 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
752
753 /* GAS Comeback Response */
754 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
755 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
756
757 /* P2P Public Action */
758 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
759 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
760 P2P_PUBLIC_ACTION_FRAME_SIZE );
761
762 /* P2P Action */
763 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
764 (v_U8_t*)P2P_ACTION_FRAME,
765 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -0700766
767#ifdef WLAN_FEATURE_11W
768 /* SA Query Response Action Frame */
769 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
770 (v_U8_t*)SA_QUERY_FRAME_RSP,
771 SA_QUERY_FRAME_RSP_SIZE );
772#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -0700773}
774
775#ifdef FEATURE_WLAN_WAPI
776void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
777 const u8 *mac_addr, u8 *key , int key_Len)
778{
779 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
780 tCsrRoamSetKey setKey;
781 v_BOOL_t isConnected = TRUE;
782 int status = 0;
783 v_U32_t roamId= 0xFF;
784 tANI_U8 *pKeyPtr = NULL;
785 int n = 0;
786
787 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
788 __func__,pAdapter->device_mode);
789
Gopichand Nakkalae7480202013-02-11 15:24:22 +0530790 vos_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Jeff Johnson295189b2012-06-20 16:38:30 -0700791 setKey.keyId = key_index; // Store Key ID
792 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
793 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
794 setKey.paeRole = 0 ; // the PAE role
795 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
796 {
797 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
798 }
799 else
800 {
801 isConnected = hdd_connIsConnected(pHddStaCtx);
802 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
803 }
804 setKey.keyLength = key_Len;
805 pKeyPtr = setKey.Key;
806 memcpy( pKeyPtr, key, key_Len);
807
808 hddLog(VOS_TRACE_LEVEL_INFO,"\n%s: WAPI KEY LENGTH:0x%04x",
809 __func__, key_Len);
810 for (n = 0 ; n < key_Len; n++)
811 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
812 __func__,n,setKey.Key[n]);
813
814 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
815 if ( isConnected )
816 {
817 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
818 pAdapter->sessionId, &setKey, &roamId );
819 }
820 if ( status != 0 )
821 {
822 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
823 "[%4d] sme_RoamSetKey returned ERROR status= %d",
824 __LINE__, status );
825 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
826 }
827}
828#endif /* FEATURE_WLAN_WAPI*/
829
830#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
831int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
832 beacon_data_t **ppBeacon,
833 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700834#else
835int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
836 beacon_data_t **ppBeacon,
837 struct cfg80211_beacon_data *params,
838 int dtim_period)
839#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700840{
841 int size;
842 beacon_data_t *beacon = NULL;
843 beacon_data_t *old = NULL;
844 int head_len,tail_len;
845
Jeff Johnsone7245742012-09-05 17:12:55 -0700846 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700847 if (params->head && !params->head_len)
848 return -EINVAL;
849
850 old = pAdapter->sessionCtx.ap.beacon;
851
852 if (!params->head && !old)
853 return -EINVAL;
854
855 if (params->tail && !params->tail_len)
856 return -EINVAL;
857
858#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
859 /* Kernel 3.0 is not updating dtim_period for set beacon */
860 if (!params->dtim_period)
861 return -EINVAL;
862#endif
863
864 if(params->head)
865 head_len = params->head_len;
866 else
867 head_len = old->head_len;
868
869 if(params->tail || !old)
870 tail_len = params->tail_len;
871 else
872 tail_len = old->tail_len;
873
874 size = sizeof(beacon_data_t) + head_len + tail_len;
875
876 beacon = kzalloc(size, GFP_KERNEL);
877
878 if( beacon == NULL )
879 return -ENOMEM;
880
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700881#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700882 if(params->dtim_period || !old )
883 beacon->dtim_period = params->dtim_period;
884 else
885 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700886#else
887 if(dtim_period || !old )
888 beacon->dtim_period = dtim_period;
889 else
890 beacon->dtim_period = old->dtim_period;
891#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700892
893 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
894 beacon->tail = beacon->head + head_len;
895 beacon->head_len = head_len;
896 beacon->tail_len = tail_len;
897
898 if(params->head) {
899 memcpy (beacon->head,params->head,beacon->head_len);
900 }
901 else {
902 if(old)
903 memcpy (beacon->head,old->head,beacon->head_len);
904 }
905
906 if(params->tail) {
907 memcpy (beacon->tail,params->tail,beacon->tail_len);
908 }
909 else {
910 if(old)
911 memcpy (beacon->tail,old->tail,beacon->tail_len);
912 }
913
914 *ppBeacon = beacon;
915
916 kfree(old);
917
918 return 0;
919
920}
Jeff Johnson295189b2012-06-20 16:38:30 -0700921
922v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
923{
924 int left = length;
925 v_U8_t *ptr = pIes;
926 v_U8_t elem_id,elem_len;
927
928 while(left >= 2)
929 {
930 elem_id = ptr[0];
931 elem_len = ptr[1];
932 left -= 2;
933 if(elem_len > left)
934 {
935 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700936 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -0700937 eid,elem_len,left);
938 return NULL;
939 }
940 if (elem_id == eid)
941 {
942 return ptr;
943 }
944
945 left -= elem_len;
946 ptr += (elem_len + 2);
947 }
948 return NULL;
949}
950
Jeff Johnson295189b2012-06-20 16:38:30 -0700951/* Check if rate is 11g rate or not */
952static int wlan_hdd_rate_is_11g(u8 rate)
953{
954 u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 104}; /* actual rate * 2 */
955 u8 i;
956 for (i = 0; i < 8; i++)
957 {
958 if(rate == gRateArray[i])
959 return TRUE;
960 }
961 return FALSE;
962}
963
964/* Check for 11g rate and set proper 11g only mode */
965static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
966 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
967{
968 u8 i, num_rates = pIe[0];
969
970 pIe += 1;
971 for ( i = 0; i < num_rates; i++)
972 {
973 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
974 {
975 /* If rate set have 11g rate than change the mode to 11G */
976 *pSapHw_mode = eSAP_DOT11_MODE_11g;
977 if (pIe[i] & BASIC_RATE_MASK)
978 {
979 /* If we have 11g rate as basic rate, it means mode
980 is 11g only mode.
981 */
982 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
983 *pCheckRatesfor11g = FALSE;
984 }
985 }
986 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
987 {
988 *require_ht = TRUE;
989 }
990 }
991 return;
992}
993
994static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
995{
996 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
997 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
998 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
999 u8 checkRatesfor11g = TRUE;
1000 u8 require_ht = FALSE;
1001 u8 *pIe=NULL;
1002
1003 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
1004
1005 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
1006 pBeacon->head_len, WLAN_EID_SUPP_RATES);
1007 if (pIe != NULL)
1008 {
1009 pIe += 1;
1010 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1011 &pConfig->SapHw_mode);
1012 }
1013
1014 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1015 WLAN_EID_EXT_SUPP_RATES);
1016 if (pIe != NULL)
1017 {
1018
1019 pIe += 1;
1020 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1021 &pConfig->SapHw_mode);
1022 }
1023
1024 if( pConfig->channel > 14 )
1025 {
1026 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
1027 }
1028
1029 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1030 WLAN_EID_HT_CAPABILITY);
1031
1032 if(pIe)
1033 {
1034 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
1035 if(require_ht)
1036 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
1037 }
1038}
1039
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301040static int wlan_hdd_add_ie(hdd_adapter_t* pHostapdAdapter, v_U8_t *genie,
1041 v_U8_t *total_ielen, v_U8_t *oui, v_U8_t oui_size)
1042{
1043 v_U8_t ielen = 0;
1044 v_U8_t *pIe = NULL;
1045 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1046
1047 pIe = wlan_hdd_get_vendor_oui_ie_ptr(oui, oui_size,
1048 pBeacon->tail, pBeacon->tail_len);
1049
1050 if (pIe)
1051 {
1052 ielen = pIe[1] + 2;
1053 if ((*total_ielen + ielen) <= MAX_GENIE_LEN)
1054 {
1055 vos_mem_copy(&genie[*total_ielen], pIe, ielen);
1056 }
1057 else
1058 {
1059 hddLog( VOS_TRACE_LEVEL_ERROR, "**Ie Length is too big***");
1060 return -EINVAL;
1061 }
1062 *total_ielen += ielen;
1063 }
1064 return 0;
1065}
1066
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001067#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001068static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1069 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001070#else
1071static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1072 struct cfg80211_beacon_data *params)
1073#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001074{
1075 v_U8_t *genie;
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301076 v_U8_t total_ielen = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001077 v_U8_t addIE[1] = {0};
Jeff Johnsone7245742012-09-05 17:12:55 -07001078 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001079
1080 genie = vos_mem_malloc(MAX_GENIE_LEN);
1081
1082 if(genie == NULL) {
1083
1084 return -ENOMEM;
1085 }
1086
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301087 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1088 &total_ielen, WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001089 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301090 ret = -EINVAL;
1091 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001092 }
1093
1094#ifdef WLAN_FEATURE_WFD
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301095 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1096 &total_ielen, WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE))
1097 {
1098 ret = -EINVAL;
1099 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001100 }
1101#endif
1102
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301103 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1104 &total_ielen, P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001105 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301106 ret = -EINVAL;
1107 goto done;
1108 }
1109
1110 if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode)
1111 {
1112 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1113 &total_ielen, SS_OUI_TYPE, SS_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001114 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301115 ret = -EINVAL;
1116 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001117 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001118 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001119
1120 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1121 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1122 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1123 {
1124 hddLog(LOGE,
1125 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001126 ret = -EINVAL;
1127 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001128 }
1129
1130 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1131 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1132 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1133 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1134 ==eHAL_STATUS_FAILURE)
1135 {
1136 hddLog(LOGE,
1137 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001138 ret = -EINVAL;
1139 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001140 }
1141
1142 // Added for ProResp IE
1143 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1144 {
1145 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1146 u8 probe_rsp_ie_len[3] = {0};
1147 u8 counter = 0;
1148 /* Check Probe Resp Length if it is greater then 255 then Store
1149 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1150 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1151 Store More then 255 bytes into One Variable.
1152 */
1153 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1154 {
1155 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1156 {
1157 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1158 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1159 }
1160 else
1161 {
1162 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1163 rem_probe_resp_ie_len = 0;
1164 }
1165 }
1166
1167 rem_probe_resp_ie_len = 0;
1168
1169 if (probe_rsp_ie_len[0] > 0)
1170 {
1171 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1172 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1173 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1174 probe_rsp_ie_len[0], NULL,
1175 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1176 {
1177 hddLog(LOGE,
1178 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001179 ret = -EINVAL;
1180 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001181 }
1182 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1183 }
1184
1185 if (probe_rsp_ie_len[1] > 0)
1186 {
1187 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1188 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1189 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1190 probe_rsp_ie_len[1], NULL,
1191 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1192 {
1193 hddLog(LOGE,
1194 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001195 ret = -EINVAL;
1196 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001197 }
1198 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1199 }
1200
1201 if (probe_rsp_ie_len[2] > 0)
1202 {
1203 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1204 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1205 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1206 probe_rsp_ie_len[2], NULL,
1207 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1208 {
1209 hddLog(LOGE,
1210 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001211 ret = -EINVAL;
1212 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001213 }
1214 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1215 }
1216
1217 if (probe_rsp_ie_len[1] == 0 )
1218 {
1219 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1220 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1221 eANI_BOOLEAN_FALSE) )
1222 {
1223 hddLog(LOGE,
1224 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1225 }
1226 }
1227
1228 if (probe_rsp_ie_len[2] == 0 )
1229 {
1230 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1231 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1232 eANI_BOOLEAN_FALSE) )
1233 {
1234 hddLog(LOGE,
1235 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1236 }
1237 }
1238
1239 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1240 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1241 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1242 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1243 == eHAL_STATUS_FAILURE)
1244 {
1245 hddLog(LOGE,
1246 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001247 ret = -EINVAL;
1248 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001249 }
1250 }
1251 else
1252 {
1253 // Reset WNI_CFG_PROBE_RSP Flags
1254 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1255
1256 hddLog(VOS_TRACE_LEVEL_INFO,
1257 "%s: No Probe Response IE received in set beacon",
1258 __func__);
1259 }
1260
1261 // Added for AssocResp IE
1262 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1263 {
1264 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1265 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1266 params->assocresp_ies_len, NULL,
1267 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1268 {
1269 hddLog(LOGE,
1270 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001271 ret = -EINVAL;
1272 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001273 }
1274
1275 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1276 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1277 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1278 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1279 == eHAL_STATUS_FAILURE)
1280 {
1281 hddLog(LOGE,
1282 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001283 ret = -EINVAL;
1284 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001285 }
1286 }
1287 else
1288 {
1289 hddLog(VOS_TRACE_LEVEL_INFO,
1290 "%s: No Assoc Response IE received in set beacon",
1291 __func__);
1292
1293 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1294 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1295 eANI_BOOLEAN_FALSE) )
1296 {
1297 hddLog(LOGE,
1298 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1299 }
1300 }
1301
Jeff Johnsone7245742012-09-05 17:12:55 -07001302done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001303 vos_mem_free(genie);
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301304 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07001305}
Jeff Johnson295189b2012-06-20 16:38:30 -07001306
1307/*
1308 * FUNCTION: wlan_hdd_validate_operation_channel
1309 * called by wlan_hdd_cfg80211_start_bss() and
1310 * wlan_hdd_cfg80211_set_channel()
1311 * This function validates whether given channel is part of valid
1312 * channel list.
1313 */
1314static VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
1315{
1316
1317 v_U32_t num_ch = 0;
1318 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1319 u32 indx = 0;
1320 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301321 v_U8_t fValidChannel = FALSE, count = 0;
1322 hdd_config_t *hdd_pConfig_ini= (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07001323
1324 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1325
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301326 if ( hdd_pConfig_ini->sapAllowAllChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001327 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301328 /* Validate the channel */
1329 for (count = RF_CHAN_1 ; count <= RF_CHAN_165 ; count++)
Jeff Johnson295189b2012-06-20 16:38:30 -07001330 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301331 if ( channel == rfChannels[count].channelNum )
1332 {
1333 fValidChannel = TRUE;
1334 break;
1335 }
1336 }
1337 if (fValidChannel != TRUE)
1338 {
1339 hddLog(VOS_TRACE_LEVEL_ERROR,
1340 "%s: Invalid Channel [%d]", __func__, channel);
1341 return VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001342 }
1343 }
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301344 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001345 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301346 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1347 valid_ch, &num_ch))
1348 {
1349 hddLog(VOS_TRACE_LEVEL_ERROR,
1350 "%s: failed to get valid channel list", __func__);
1351 return VOS_STATUS_E_FAILURE;
1352 }
1353 for (indx = 0; indx < num_ch; indx++)
1354 {
1355 if (channel == valid_ch[indx])
1356 {
1357 break;
1358 }
1359 }
1360
1361 if (indx >= num_ch)
1362 {
1363 hddLog(VOS_TRACE_LEVEL_ERROR,
1364 "%s: Invalid Channel [%d]", __func__, channel);
1365 return VOS_STATUS_E_FAILURE;
1366 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001367 }
1368 return VOS_STATUS_SUCCESS;
1369
1370}
1371
Viral Modi3a32cc52013-02-08 11:14:52 -08001372/**
1373 * FUNCTION: wlan_hdd_cfg80211_set_channel
1374 * This function is used to set the channel number
1375 */
1376static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
1377 struct ieee80211_channel *chan,
1378 enum nl80211_channel_type channel_type
1379 )
1380{
1381 v_U32_t num_ch = 0;
Jeff Johnson4416a782013-03-25 14:17:50 -07001382 int channel = 0;
Viral Modi3a32cc52013-02-08 11:14:52 -08001383 hdd_adapter_t *pAdapter = NULL;
1384 int freq = chan->center_freq; /* freq is in MHZ */
1385
1386 ENTER();
1387
1388 if( NULL == dev )
1389 {
1390 hddLog(VOS_TRACE_LEVEL_ERROR,
1391 "%s: Called with dev = NULL.\n", __func__);
1392 return -ENODEV;
1393 }
1394 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1395
1396 hddLog(VOS_TRACE_LEVEL_INFO,
1397 "%s: device_mode = %d freq = %d \n",__func__,
1398 pAdapter->device_mode, chan->center_freq);
1399 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1400 {
1401 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1402 return -EAGAIN;
1403 }
1404
1405 /*
1406 * Do freq to chan conversion
1407 * TODO: for 11a
1408 */
1409
1410 channel = ieee80211_frequency_to_channel(freq);
1411
1412 /* Check freq range */
1413 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
1414 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
1415 {
1416 hddLog(VOS_TRACE_LEVEL_ERROR,
1417 "%s: Channel [%d] is outside valid range from %d to %d\n",
1418 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
1419 WNI_CFG_CURRENT_CHANNEL_STAMAX);
1420 return -EINVAL;
1421 }
1422
1423 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1424
Gopichand Nakkala6ab19562013-03-07 13:59:42 +05301425 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode) &&
1426 (WLAN_HDD_P2P_GO != pAdapter->device_mode))
Viral Modi3a32cc52013-02-08 11:14:52 -08001427 {
1428 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
1429 {
1430 hddLog(VOS_TRACE_LEVEL_ERROR,
1431 "%s: Invalid Channel [%d] \n", __func__, channel);
1432 return -EINVAL;
1433 }
1434 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1435 "%s: set channel to [%d] for device mode =%d",
1436 __func__, channel,pAdapter->device_mode);
1437 }
1438 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Viral Modi3a32cc52013-02-08 11:14:52 -08001439 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Viral Modi3a32cc52013-02-08 11:14:52 -08001440 )
1441 {
1442 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
1443 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
1444 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1445
1446 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
1447 {
1448 /* Link is up then return cant set channel*/
1449 hddLog( VOS_TRACE_LEVEL_ERROR,
1450 "%s: IBSS Associated, can't set the channel\n", __func__);
1451 return -EINVAL;
1452 }
1453
1454 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
1455 pHddStaCtx->conn_info.operationChannel = channel;
1456 pRoamProfile->ChannelInfo.ChannelList =
1457 &pHddStaCtx->conn_info.operationChannel;
1458 }
1459 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Viral Modi3a32cc52013-02-08 11:14:52 -08001460 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Viral Modi3a32cc52013-02-08 11:14:52 -08001461 )
1462 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301463 if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
1464 {
1465 if(VOS_STATUS_SUCCESS !=
1466 wlan_hdd_validate_operation_channel(pAdapter,channel))
1467 {
1468 hddLog(VOS_TRACE_LEVEL_ERROR,
1469 "%s: Invalid Channel [%d] \n", __func__, channel);
1470 return -EINVAL;
1471 }
1472 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1473 }
1474 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
Viral Modi3a32cc52013-02-08 11:14:52 -08001475 {
1476 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
1477
1478 /* If auto channel selection is configured as enable/ 1 then ignore
1479 channel set by supplicant
1480 */
1481 if ( cfg_param->apAutoChannelSelection )
1482 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301483 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel =
1484 AUTO_CHANNEL_SELECT;
Viral Modi3a32cc52013-02-08 11:14:52 -08001485 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1486 "%s: set channel to auto channel (0) for device mode =%d",
1487 __func__, pAdapter->device_mode);
1488 }
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301489 else
1490 {
1491 if(VOS_STATUS_SUCCESS !=
1492 wlan_hdd_validate_operation_channel(pAdapter,channel))
1493 {
1494 hddLog(VOS_TRACE_LEVEL_ERROR,
1495 "%s: Invalid Channel [%d] \n", __func__, channel);
1496 return -EINVAL;
1497 }
1498 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1499 }
Viral Modi3a32cc52013-02-08 11:14:52 -08001500 }
1501 }
1502 else
1503 {
1504 hddLog(VOS_TRACE_LEVEL_FATAL,
1505 "%s: Invalid device mode failed to set valid channel", __func__);
1506 return -EINVAL;
1507 }
1508 EXIT();
1509 return 0;
1510}
1511
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301512/*
1513 * FUNCTION: wlan_hdd_select_cbmode
1514 * called by wlan_hdd_cfg80211_start_bss() and
1515 * This function selects the cbmode based on primary channel
1516 */
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001517VOS_STATUS wlan_sap_select_cbmode(void *pAdapter,eSapPhyMode SapHw_mode, v_U8_t channel)
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301518{
1519 tSmeConfigParams smeConfig;
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001520 hdd_context_t *pHddCtx = ( hdd_context_t *) pAdapter;
1521 hdd_config_t *pConfigIni = ((hdd_context_t *)(pAdapter))->cfg_ini;
1522
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301523 if(
1524#ifdef WLAN_FEATURE_11AC
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001525 SapHw_mode != eSAP_DOT11_MODE_11ac &&
1526 SapHw_mode != eSAP_DOT11_MODE_11ac_ONLY &&
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301527#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001528 SapHw_mode != eSAP_DOT11_MODE_11n &&
1529 SapHw_mode != eSAP_DOT11_MODE_11n_ONLY
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301530 )
1531 {
1532 return VOS_STATUS_SUCCESS;
1533 }
1534
1535 if (!pConfigIni->nChannelBondingMode5GHz) {
1536 return VOS_STATUS_SUCCESS;
1537 }
1538
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001539 //channel = pSapConfig->channel;
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301540 vos_mem_zero(&smeConfig, sizeof (tSmeConfigParams));
1541
1542 sme_GetConfigParam(pHddCtx->hHal, &smeConfig);
1543
1544#ifdef WLAN_FEATURE_11AC
1545
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001546 if ( SapHw_mode == eSAP_DOT11_MODE_11ac ||
1547 SapHw_mode == eSAP_DOT11_MODE_11ac_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301548 {
1549 if ( channel== 36 || channel == 52 || channel == 100 ||
1550 channel == 116 || channel == 149 )
1551 {
1552 smeConfig.csrConfig.channelBondingMode5GHz =
1553 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW - 1;
1554 }
1555 else if ( channel == 40 || channel == 56 || channel == 104 ||
1556 channel == 120 || channel == 153 )
1557 {
1558 smeConfig.csrConfig.channelBondingMode5GHz =
1559 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW - 1;
1560 }
1561 else if ( channel == 44 || channel == 60 || channel == 108 ||
1562 channel == 124 || channel == 157 )
1563 {
1564 smeConfig.csrConfig.channelBondingMode5GHz =
1565 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH -1;
1566 }
1567 else if ( channel == 48 || channel == 64 || channel == 112 ||
1568 channel == 128 || channel == 161 )
1569 {
1570 smeConfig.csrConfig.channelBondingMode5GHz =
1571 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH - 1;
1572 }
Shailender Karmuchi84f11f02013-02-12 17:11:45 -08001573 else if ( channel == 165 )
1574 {
1575 smeConfig.csrConfig.channelBondingMode5GHz = 0;
1576 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301577 }
1578#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001579 if ( SapHw_mode == eSAP_DOT11_MODE_11n ||
1580 SapHw_mode == eSAP_DOT11_MODE_11n_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301581 {
1582 if ( channel== 40 || channel == 48 || channel == 56 ||
1583 channel == 64 || channel == 104 || channel == 112 ||
1584 channel == 120 || channel == 128 || channel == 136 ||
1585 channel == 144 || channel == 153 || channel == 161 )
1586 {
1587 smeConfig.csrConfig.channelBondingMode5GHz = 1;
1588 }
1589 else if ( channel== 36 || channel == 44 || channel == 52 ||
1590 channel == 60 || channel == 100 || channel == 108 ||
1591 channel == 116 || channel == 124 || channel == 132 ||
1592 channel == 140 || channel == 149 || channel == 157 )
1593 {
1594 smeConfig.csrConfig.channelBondingMode5GHz = 2;
1595 }
Shailender Karmuchi84f11f02013-02-12 17:11:45 -08001596 else if ( channel == 165 )
1597 {
1598 smeConfig.csrConfig.channelBondingMode5GHz = 0;
1599 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301600 }
1601 pr_info ("cbmode selected=%ld\n",smeConfig.csrConfig.channelBondingMode5GHz);
1602
1603 sme_UpdateConfig (pHddCtx->hHal,&smeConfig);
1604 return VOS_STATUS_SUCCESS;
1605}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001606
Jeff Johnson295189b2012-06-20 16:38:30 -07001607#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1608static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1609 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001610#else
1611static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1612 struct cfg80211_beacon_data *params,
1613 const u8 *ssid, size_t ssid_len,
1614 enum nl80211_hidden_ssid hidden_ssid)
1615#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001616{
1617 tsap_Config_t *pConfig;
1618 beacon_data_t *pBeacon = NULL;
1619 struct ieee80211_mgmt *pMgmt_frame;
1620 v_U8_t *pIe=NULL;
1621 v_U16_t capab_info;
1622 eCsrAuthType RSNAuthType;
1623 eCsrEncryptionType RSNEncryptType;
1624 eCsrEncryptionType mcRSNEncryptType;
1625 int status = VOS_STATUS_SUCCESS;
1626 tpWLAN_SAPEventCB pSapEventCallback;
1627 hdd_hostapd_state_t *pHostapdState;
1628 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1629 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301630 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001631 struct qc_mac_acl_entry *acl_entry = NULL;
1632 v_SINT_t i;
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001633 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001634
1635 ENTER();
1636
1637 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1638
1639 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1640
1641 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1642
1643 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1644
1645 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1646
1647 //channel is already set in the set_channel Call back
1648 //pConfig->channel = pCommitConfig->channel;
1649
1650 /*Protection parameter to enable or disable*/
1651 pConfig->protEnabled =
1652 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1653
1654 pConfig->dtim_period = pBeacon->dtim_period;
1655
1656 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1657 pConfig->dtim_period);
1658
1659
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001660 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001661 {
1662 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001663 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001664 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001665 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001666 tANI_BOOLEAN restartNeeded;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001667 pConfig->ieee80211d = 1;
1668 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1669 sme_setRegInfo(hHal, pConfig->countryCode);
1670 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
Jeff Johnson295189b2012-06-20 16:38:30 -07001671 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001672 else
1673 {
1674 pConfig->ieee80211d = 0;
1675 }
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301676 /*
1677 * If auto channel is configured i.e. channel is 0,
1678 * so skip channel validation.
1679 */
1680 if( AUTO_CHANNEL_SELECT != pConfig->channel )
1681 {
1682 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1683 {
1684 hddLog(VOS_TRACE_LEVEL_ERROR,
1685 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1686 return -EINVAL;
1687 }
1688 }
1689 else
1690 {
1691 if(1 != pHddCtx->is_dynamic_channel_range_set)
1692 {
1693 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
1694 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
1695 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
1696 }
1697 pHddCtx->is_dynamic_channel_range_set = 0;
1698 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001699 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001700 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001701 {
1702 pConfig->ieee80211d = 0;
1703 }
1704 pConfig->authType = eSAP_AUTO_SWITCH;
1705
1706 capab_info = pMgmt_frame->u.beacon.capab_info;
1707
1708 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
1709 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1710
1711 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1712
1713 /*Set wps station to configured*/
1714 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1715
1716 if(pIe)
1717 {
1718 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1719 {
1720 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1721 return -EINVAL;
1722 }
1723 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1724 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001725 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001726 /* Check 15 bit of WPS IE as it contain information for wps state
1727 * WPS state
1728 */
1729 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1730 {
1731 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1732 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1733 {
1734 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1735 }
1736 }
1737 }
1738 else
1739 {
1740 pConfig->wps_state = SAP_WPS_DISABLED;
1741 }
1742 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
1743
1744 pConfig->RSNWPAReqIELength = 0;
1745 pConfig->pRSNWPAReqIE = NULL;
1746 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1747 WLAN_EID_RSN);
1748 if(pIe && pIe[1])
1749 {
1750 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1751 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1752 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1753 /* The actual processing may eventually be more extensive than
1754 * this. Right now, just consume any PMKIDs that are sent in
1755 * by the app.
1756 * */
1757 status = hdd_softap_unpackIE(
1758 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1759 &RSNEncryptType,
1760 &mcRSNEncryptType,
1761 &RSNAuthType,
1762 pConfig->pRSNWPAReqIE[1]+2,
1763 pConfig->pRSNWPAReqIE );
1764
1765 if( VOS_STATUS_SUCCESS == status )
1766 {
1767 /* Now copy over all the security attributes you have
1768 * parsed out
1769 * */
1770 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1771 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1772 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1773 = RSNEncryptType;
1774 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1775 "EncryptionType = %d mcEncryptionType = %d\n"),
1776 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1777 }
1778 }
1779
1780 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1781 pBeacon->tail, pBeacon->tail_len);
1782
1783 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1784 {
1785 if (pConfig->pRSNWPAReqIE)
1786 {
1787 /*Mixed mode WPA/WPA2*/
1788 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1789 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1790 }
1791 else
1792 {
1793 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1794 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1795 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1796 status = hdd_softap_unpackIE(
1797 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1798 &RSNEncryptType,
1799 &mcRSNEncryptType,
1800 &RSNAuthType,
1801 pConfig->pRSNWPAReqIE[1]+2,
1802 pConfig->pRSNWPAReqIE );
1803
1804 if( VOS_STATUS_SUCCESS == status )
1805 {
1806 /* Now copy over all the security attributes you have
1807 * parsed out
1808 * */
1809 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1810 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1811 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1812 = RSNEncryptType;
1813 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1814 "EncryptionType = %d mcEncryptionType = %d\n"),
1815 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1816 }
1817 }
1818 }
1819
Jeff Johnson4416a782013-03-25 14:17:50 -07001820 if (pConfig->RSNWPAReqIELength > sizeof wpaRsnIEdata) {
1821 hddLog( VOS_TRACE_LEVEL_ERROR, "**RSNWPAReqIELength is too large***");
1822 return -EINVAL;
1823 }
1824
Jeff Johnson295189b2012-06-20 16:38:30 -07001825 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1826
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001827#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001828 if (params->ssid != NULL)
1829 {
1830 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1831 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1832 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1833 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1834 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001835#else
1836 if (ssid != NULL)
1837 {
1838 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1839 pConfig->SSIDinfo.ssid.length = ssid_len;
1840 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1841 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1842 }
1843#endif
1844
Jeff Johnson295189b2012-06-20 16:38:30 -07001845 vos_mem_copy(pConfig->self_macaddr.bytes,
1846 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1847
1848 /* default value */
1849 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1850 pConfig->num_accept_mac = 0;
1851 pConfig->num_deny_mac = 0;
1852
1853 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1854 pBeacon->tail, pBeacon->tail_len);
1855
1856 /* pIe for black list is following form:
1857 type : 1 byte
1858 length : 1 byte
1859 OUI : 4 bytes
1860 acl type : 1 byte
1861 no of mac addr in black list: 1 byte
1862 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1863 */
1864 if ((pIe != NULL) && (pIe[1] != 0))
1865 {
1866 pConfig->SapMacaddr_acl = pIe[6];
1867 pConfig->num_deny_mac = pIe[7];
1868 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1869 pIe[6], pIe[7]);
1870 if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
1871 pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
1872 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1873 for (i = 0; i < pConfig->num_deny_mac; i++)
1874 {
1875 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1876 acl_entry++;
1877 }
1878 }
1879 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1880 pBeacon->tail, pBeacon->tail_len);
1881
1882 /* pIe for white list is following form:
1883 type : 1 byte
1884 length : 1 byte
1885 OUI : 4 bytes
1886 acl type : 1 byte
1887 no of mac addr in white list: 1 byte
1888 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1889 */
1890 if ((pIe != NULL) && (pIe[1] != 0))
1891 {
1892 pConfig->SapMacaddr_acl = pIe[6];
1893 pConfig->num_accept_mac = pIe[7];
1894 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
1895 pIe[6], pIe[7]);
1896 if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
1897 pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
1898 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1899 for (i = 0; i < pConfig->num_accept_mac; i++)
1900 {
1901 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1902 acl_entry++;
1903 }
1904 }
1905 wlan_hdd_set_sapHwmode(pHostapdAdapter);
1906
Jeff Johnsone7245742012-09-05 17:12:55 -07001907#ifdef WLAN_FEATURE_11AC
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08001908 /* Overwrite the hostapd setting for HW mode only for 11ac.
1909 * This is valid only if mode is set to 11n in hostapd and either AUTO or 11ac in .ini .
1910 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode) */
1911 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
1912 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
1913 (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
1914 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1915 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07001916 {
1917 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
1918 }
1919#endif
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301920
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001921 if( AUTO_CHANNEL_SELECT != pConfig->channel)
1922 wlan_sap_select_cbmode((WLAN_HDD_GET_CTX(pHostapdAdapter)),pConfig->SapHw_mode,pConfig->channel);
Jeff Johnson295189b2012-06-20 16:38:30 -07001923 // ht_capab is not what the name conveys,this is used for protection bitmap
1924 pConfig->ht_capab =
1925 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
1926
1927 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
1928 {
1929 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
1930 return -EINVAL;
1931 }
1932
1933 //Uapsd Enabled Bit
1934 pConfig->UapsdEnable =
1935 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
1936 //Enable OBSS protection
1937 pConfig->obssProtEnabled =
1938 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
1939
1940 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
1941 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
1942 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
1943 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
1944 (int)pConfig->channel);
1945 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
1946 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
1947 pConfig->authType);
1948 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
1949 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
1950 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
1951 pConfig->protEnabled, pConfig->obssProtEnabled);
1952
1953 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
1954 {
1955 //Bss already started. just return.
1956 //TODO Probably it should update some beacon params.
1957 hddLog( LOGE, "Bss Already started...Ignore the request");
1958 EXIT();
1959 return 0;
1960 }
1961
1962 pConfig->persona = pHostapdAdapter->device_mode;
1963
1964 pSapEventCallback = hdd_hostapd_SAPEventCB;
1965 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
1966 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
1967 {
1968 hddLog(LOGE,FL("SAP Start Bss fail\n"));
1969 return -EINVAL;
1970 }
1971
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001972 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07001973 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
1974
1975 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1976
1977 if (!VOS_IS_STATUS_SUCCESS(status))
1978 {
1979 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1980 ("ERROR: HDD vos wait for single_event failed!!\n"));
1981 VOS_ASSERT(0);
1982 }
1983
1984 //Succesfully started Bss update the state bit.
1985 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
1986
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001987#ifdef WLAN_FEATURE_P2P_DEBUG
1988 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
1989 {
1990 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
1991 {
1992 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1993 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001994 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001995 }
1996 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
1997 {
1998 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1999 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002000 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002001 }
2002 }
2003#endif
2004
Jeff Johnson295189b2012-06-20 16:38:30 -07002005 pHostapdState->bCommit = TRUE;
2006 EXIT();
2007
2008 return 0;
2009}
2010
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002011#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002012static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
2013 struct net_device *dev,
2014 struct beacon_parameters *params)
2015{
2016 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2017 int status=VOS_STATUS_SUCCESS;
2018
2019 ENTER();
2020
2021 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
2022
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002023 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2024 {
2025 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2026 "%s:LOGP in Progress. Ignore!!!", __func__);
2027 return -EAGAIN;
2028 }
2029
Jeff Johnson295189b2012-06-20 16:38:30 -07002030 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002031 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002032 )
2033 {
2034 beacon_data_t *old,*new;
2035
2036 old = pAdapter->sessionCtx.ap.beacon;
2037
2038 if (old)
2039 return -EALREADY;
2040
2041 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2042
2043 if(status != VOS_STATUS_SUCCESS)
2044 {
2045 hddLog(VOS_TRACE_LEVEL_FATAL,
2046 "%s:Error!!! Allocating the new beacon\n",__func__);
2047 return -EINVAL;
2048 }
2049
2050 pAdapter->sessionCtx.ap.beacon = new;
2051
2052 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2053 }
2054
2055 EXIT();
2056 return status;
2057}
2058
2059static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
2060 struct net_device *dev,
2061 struct beacon_parameters *params)
2062{
2063 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2064 int status=VOS_STATUS_SUCCESS;
2065
2066 ENTER();
2067
2068 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2069 __func__,pAdapter->device_mode);
2070
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002071 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2072 {
2073 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2074 "%s:LOGP in Progress. Ignore!!!", __func__);
2075 return -EAGAIN;
2076 }
2077
Jeff Johnson295189b2012-06-20 16:38:30 -07002078 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002079 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002080 )
2081 {
2082 beacon_data_t *old,*new;
2083
2084 old = pAdapter->sessionCtx.ap.beacon;
2085
2086 if (!old)
2087 return -ENOENT;
2088
2089 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2090
2091 if(status != VOS_STATUS_SUCCESS) {
2092 hddLog(VOS_TRACE_LEVEL_FATAL,
2093 "%s: Error!!! Allocating the new beacon\n",__func__);
2094 return -EINVAL;
2095 }
2096
2097 pAdapter->sessionCtx.ap.beacon = new;
2098
2099 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2100 }
2101
2102 EXIT();
2103 return status;
2104}
2105
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002106#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
2107
2108#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002109static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
2110 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002111#else
2112static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
2113 struct net_device *dev)
2114#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002115{
2116 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07002117 hdd_context_t *pHddCtx = NULL;
2118 hdd_scaninfo_t *pScanInfo = NULL;
2119 hdd_adapter_t *staAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002120 VOS_STATUS status = 0;
2121
2122 ENTER();
2123
2124 if (NULL == pAdapter)
2125 {
2126 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002127 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002128 return -ENODEV;
2129 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002130
Jeff Johnson4416a782013-03-25 14:17:50 -07002131 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002132 if (NULL == pHddCtx)
2133 {
2134 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002135 "%s: HDD context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002136 return -ENODEV;
2137 }
Jeff Johnson4416a782013-03-25 14:17:50 -07002138 if (pHddCtx->isLogpInProgress)
2139 {
2140 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2141 "%s:LOGP in Progress. Ignore!!!", __func__);
2142 return -EAGAIN;
2143 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002144
2145 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
2146 if (NULL == staAdapter)
2147 {
2148 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
2149 if (NULL == staAdapter)
2150 {
2151 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002152 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002153 return -ENODEV;
2154 }
2155 }
2156
2157 pScanInfo = &pHddCtx->scan_info;
2158
Jeff Johnson4416a782013-03-25 14:17:50 -07002159 if (pHddCtx->isLogpInProgress)
Jeff Johnson295189b2012-06-20 16:38:30 -07002160 {
2161 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2162 return -EAGAIN;
2163 }
2164
2165 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2166
2167 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2168 __func__,pAdapter->device_mode);
2169
Jeff Johnsone7245742012-09-05 17:12:55 -07002170 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
2171 {
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002172 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Jeff Johnsone7245742012-09-05 17:12:55 -07002173 hdd_abort_mac_scan(staAdapter->pHddCtx);
2174 status = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002175 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07002176 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
2177 if (!status)
2178 {
2179 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson902c9832012-12-10 14:28:09 -08002180 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002181 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07002182 VOS_ASSERT(pScanInfo->mScanPending);
2183 return 0;
2184 }
2185 }
2186
Jeff Johnson295189b2012-06-20 16:38:30 -07002187 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002188 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002189 )
2190 {
2191 beacon_data_t *old;
2192
2193 old = pAdapter->sessionCtx.ap.beacon;
2194
2195 if (!old)
2196 return -ENOENT;
2197
Jeff Johnson295189b2012-06-20 16:38:30 -07002198 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002199
2200 mutex_lock(&pHddCtx->sap_lock);
2201 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2202 {
Jeff Johnson4416a782013-03-25 14:17:50 -07002203 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss(pHddCtx->pvosContext) ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07002204 {
2205 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2206
2207 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2208
2209 if (!VOS_IS_STATUS_SUCCESS(status))
2210 {
2211 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2212 ("ERROR: HDD vos wait for single_event failed!!\n"));
2213 VOS_ASSERT(0);
2214 }
2215 }
2216 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2217 }
2218 mutex_unlock(&pHddCtx->sap_lock);
2219
2220 if(status != VOS_STATUS_SUCCESS)
2221 {
2222 hddLog(VOS_TRACE_LEVEL_FATAL,
2223 "%s:Error!!! Stopping the BSS\n",__func__);
2224 return -EINVAL;
2225 }
2226
Jeff Johnson4416a782013-03-25 14:17:50 -07002227 if (ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002228 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
2229 ==eHAL_STATUS_FAILURE)
2230 {
2231 hddLog(LOGE,
2232 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
2233 }
2234
Jeff Johnson4416a782013-03-25 14:17:50 -07002235 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002236 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2237 eANI_BOOLEAN_FALSE) )
2238 {
2239 hddLog(LOGE,
2240 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
2241 }
2242
2243 // Reset WNI_CFG_PROBE_RSP Flags
2244 wlan_hdd_reset_prob_rspies(pAdapter);
2245
2246 pAdapter->sessionCtx.ap.beacon = NULL;
2247 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002248#ifdef WLAN_FEATURE_P2P_DEBUG
2249 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
2250 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
2251 {
2252 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
2253 "GO got removed");
2254 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
2255 }
2256#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002257 }
2258 EXIT();
2259 return status;
2260}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002261
2262#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2263
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302264static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2265 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002266 struct cfg80211_ap_settings *params)
2267{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302268 hdd_adapter_t *pAdapter;
2269 hdd_context_t *pHddCtx;
2270 int status = 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002271
2272 ENTER();
2273
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302274 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002275 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302276 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2277 "%s: Device is Null", __func__);
2278 return -ENODEV;
2279 }
2280
2281 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2282 if (NULL == pAdapter)
2283 {
2284 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2285 "%s: HDD adapter is Null", __func__);
2286 return -ENODEV;
2287 }
2288
2289 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2290 {
2291 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2292 "%s: HDD adapter magic is invalid", __func__);
2293 return -ENODEV;
2294 }
2295
2296 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2297 if (NULL == pHddCtx)
2298 {
2299 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2300 "%s: HDD context is Null", __func__);
2301 return -ENODEV;
2302 }
2303
2304 if (pHddCtx->isLogpInProgress)
2305 {
2306 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2307 "%s: LOGP in Progress. Ignore!!!", __func__);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002308 return -EAGAIN;
2309 }
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302310
2311 if (pHddCtx->isLoadUnloadInProgress)
2312 {
2313 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2314 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
2315 return -EAGAIN;
2316 }
2317
2318 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2319 __func__, pAdapter->device_mode);
2320
2321 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002322 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002323 )
2324 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302325 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002326
2327 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302328
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002329 if (old)
2330 return -EALREADY;
2331
2332 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2333
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302334 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002335 {
2336 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302337 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002338 return -EINVAL;
2339 }
2340 pAdapter->sessionCtx.ap.beacon = new;
Viral Modi3a32cc52013-02-08 11:14:52 -08002341#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2342 wlan_hdd_cfg80211_set_channel(wiphy, dev, params->channel, params->channel_type);
2343#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002344 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2345 params->ssid_len, params->hidden_ssid);
2346 }
2347
2348 EXIT();
2349 return status;
2350}
2351
2352
2353static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
2354 struct net_device *dev,
2355 struct cfg80211_beacon_data *params)
2356{
2357 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2358 int status=VOS_STATUS_SUCCESS;
2359
2360 ENTER();
2361
2362 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2363 __func__, pAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002364 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2365 {
2366 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2367 return -EAGAIN;
2368 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002369
2370 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002371 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002372 )
2373 {
2374 beacon_data_t *old,*new;
2375
2376 old = pAdapter->sessionCtx.ap.beacon;
2377
2378 if (!old)
2379 return -ENOENT;
2380
2381 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2382
2383 if(status != VOS_STATUS_SUCCESS) {
2384 hddLog(VOS_TRACE_LEVEL_FATAL,
2385 "%s: Error!!! Allocating the new beacon\n",__func__);
2386 return -EINVAL;
2387 }
2388
2389 pAdapter->sessionCtx.ap.beacon = new;
2390
2391 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2392 }
2393
2394 EXIT();
2395 return status;
2396}
2397
2398#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2399
Jeff Johnson295189b2012-06-20 16:38:30 -07002400
2401static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2402 struct net_device *dev,
2403 struct bss_parameters *params)
2404{
2405 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2406
2407 ENTER();
2408
2409 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2410 __func__,pAdapter->device_mode);
2411
2412 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002413 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002414 )
2415 {
2416 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2417 * want to update this parameter */
2418 if (-1 != params->ap_isolate)
2419 {
2420 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
2421 }
2422 }
2423
2424 EXIT();
2425 return 0;
2426}
2427
2428/*
2429 * FUNCTION: wlan_hdd_cfg80211_change_iface
2430 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2431 */
2432int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2433 struct net_device *ndev,
2434 enum nl80211_iftype type,
2435 u32 *flags,
2436 struct vif_params *params
2437 )
2438{
2439 struct wireless_dev *wdev;
2440 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2441 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002442 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002443 tCsrRoamProfile *pRoamProfile = NULL;
2444 eCsrRoamBssType LastBSSType;
2445 hdd_config_t *pConfig = pHddCtx->cfg_ini;
2446 eMib_dot11DesiredBssType connectedBssType;
2447 VOS_STATUS status;
2448
2449 ENTER();
2450
2451 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2452 {
2453 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2454 return -EAGAIN;
2455 }
2456
2457 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2458 __func__, pAdapter->device_mode);
2459
2460 wdev = ndev->ieee80211_ptr;
2461
2462#ifdef WLAN_BTAMP_FEATURE
2463 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2464 (NL80211_IFTYPE_ADHOC == type)||
2465 (NL80211_IFTYPE_AP == type)||
2466 (NL80211_IFTYPE_P2P_GO == type))
2467 {
2468 pHddCtx->isAmpAllowed = VOS_FALSE;
2469 // stop AMP traffic
2470 status = WLANBAP_StopAmp();
2471 if(VOS_STATUS_SUCCESS != status )
2472 {
2473 pHddCtx->isAmpAllowed = VOS_TRUE;
2474 hddLog(VOS_TRACE_LEVEL_FATAL,
2475 "%s: Failed to stop AMP", __func__);
2476 return -EINVAL;
2477 }
2478 }
2479#endif //WLAN_BTAMP_FEATURE
2480 /* Reset the current device mode bit mask*/
2481 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2482
2483 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07002484 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002485 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002486 )
2487 {
2488 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2489 pRoamProfile = &pWextState->roamProfile;
2490 LastBSSType = pRoamProfile->BSSType;
2491
2492 switch (type)
2493 {
2494 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002495 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002496 hddLog(VOS_TRACE_LEVEL_INFO,
2497 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2498 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002499#ifdef WLAN_FEATURE_11AC
2500 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2501 {
2502 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2503 }
2504#endif
2505 pRoamProfile->phyMode =
2506 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002507 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002508 //Check for sub-string p2p to confirm its a p2p interface
2509 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002510 {
2511 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2512 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2513 }
2514 else
2515 {
2516 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002517 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002518 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002519 break;
2520 case NL80211_IFTYPE_ADHOC:
2521 hddLog(VOS_TRACE_LEVEL_INFO,
2522 "%s: setting interface Type to ADHOC", __func__);
2523 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2524 pRoamProfile->phyMode =
2525 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
2526 wdev->iftype = type;
2527 break;
2528
2529 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002530 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002531 {
2532 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2533 "%s: setting interface Type to %s", __func__,
2534 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2535
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002536 //Cancel any remain on channel for GO mode
2537 if (NL80211_IFTYPE_P2P_GO == type)
2538 {
2539 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2540 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002541 if (NL80211_IFTYPE_AP == type)
2542 {
2543 /* As Loading WLAN Driver one interface being created for p2p device
2544 * address. This will take one HW STA and the max number of clients
2545 * that can connect to softAP will be reduced by one. so while changing
2546 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2547 * interface as it is not required in SoftAP mode.
2548 */
2549
2550 // Get P2P Adapter
2551 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2552
2553 if (pP2pAdapter)
2554 {
2555 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2556 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2557 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2558 }
2559 }
2560
Jeff Johnson295189b2012-06-20 16:38:30 -07002561 //De-init the adapter.
2562 hdd_stop_adapter( pHddCtx, pAdapter );
2563 hdd_deinit_adapter( pHddCtx, pAdapter );
2564 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
Jeff Johnson295189b2012-06-20 16:38:30 -07002565 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2566 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002567
2568 //Disable BMPS and IMPS if enabled
2569 //before starting Go
2570 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2571 {
2572 if(VOS_STATUS_E_FAILURE ==
2573 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2574 {
2575 //Fail to Exit BMPS
2576 VOS_ASSERT(0);
2577 }
2578 }
2579
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002580 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2581 (pConfig->apRandomBssidEnabled))
2582 {
2583 /* To meet Android requirements create a randomized
2584 MAC address of the form 02:1A:11:Fx:xx:xx */
2585 get_random_bytes(&ndev->dev_addr[3], 3);
2586 ndev->dev_addr[0] = 0x02;
2587 ndev->dev_addr[1] = 0x1A;
2588 ndev->dev_addr[2] = 0x11;
2589 ndev->dev_addr[3] |= 0xF0;
2590 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2591 VOS_MAC_ADDR_SIZE);
2592 pr_info("wlan: Generated HotSpot BSSID "
2593 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2594 ndev->dev_addr[0],
2595 ndev->dev_addr[1],
2596 ndev->dev_addr[2],
2597 ndev->dev_addr[3],
2598 ndev->dev_addr[4],
2599 ndev->dev_addr[5]);
2600 }
2601
Jeff Johnson295189b2012-06-20 16:38:30 -07002602 hdd_set_ap_ops( pAdapter->dev );
2603
2604 status = hdd_init_ap_mode(pAdapter);
2605 if(status != VOS_STATUS_SUCCESS)
2606 {
2607 hddLog(VOS_TRACE_LEVEL_FATAL,
2608 "%s: Error initializing the ap mode", __func__);
2609 return -EINVAL;
2610 }
2611 hdd_set_conparam(1);
2612
Jeff Johnson295189b2012-06-20 16:38:30 -07002613 /*interface type changed update in wiphy structure*/
2614 if(wdev)
2615 {
2616 wdev->iftype = type;
2617 pHddCtx->change_iface = type;
2618 }
2619 else
2620 {
2621 hddLog(VOS_TRACE_LEVEL_ERROR,
2622 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2623 return -EINVAL;
2624 }
2625 goto done;
2626 }
2627
2628 default:
2629 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2630 __func__);
2631 return -EOPNOTSUPP;
2632 }
2633 }
2634 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002635 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002636 )
2637 {
2638 switch(type)
2639 {
2640 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002641 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002642 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002643 hdd_stop_adapter( pHddCtx, pAdapter );
2644 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002645 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002646 //Check for sub-string p2p to confirm its a p2p interface
2647 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002648 {
2649 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2650 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2651 }
2652 else
2653 {
2654 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002655 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002656 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002657 hdd_set_conparam(0);
2658 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002659 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2660 hdd_set_station_ops( pAdapter->dev );
2661 status = hdd_init_station_mode( pAdapter );
2662 if( VOS_STATUS_SUCCESS != status )
2663 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002664 /* In case of JB, for P2P-GO, only change interface will be called,
2665 * This is the right place to enable back bmps_imps()
2666 */
2667 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002668 goto done;
2669 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002670 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002671 wdev->iftype = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002672 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2673 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07002674 goto done;
2675 default:
2676 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2677 __func__);
2678 return -EOPNOTSUPP;
2679
2680 }
2681
2682 }
2683 else
2684 {
2685 return -EOPNOTSUPP;
2686 }
2687
2688
2689 if(pRoamProfile)
2690 {
2691 if ( LastBSSType != pRoamProfile->BSSType )
2692 {
2693 /*interface type changed update in wiphy structure*/
2694 wdev->iftype = type;
2695
2696 /*the BSS mode changed, We need to issue disconnect
2697 if connected or in IBSS disconnect state*/
2698 if ( hdd_connGetConnectedBssType(
2699 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2700 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2701 {
2702 /*need to issue a disconnect to CSR.*/
2703 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2704 if( eHAL_STATUS_SUCCESS ==
2705 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2706 pAdapter->sessionId,
2707 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2708 {
2709 wait_for_completion_interruptible_timeout(
2710 &pAdapter->disconnect_comp_var,
2711 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2712 }
2713 }
2714 }
2715 }
2716
2717done:
2718 /*set bitmask based on updated value*/
2719 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
2720#ifdef WLAN_BTAMP_FEATURE
2721 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
2722 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2723 {
2724 //we are ok to do AMP
2725 pHddCtx->isAmpAllowed = VOS_TRUE;
2726 }
2727#endif //WLAN_BTAMP_FEATURE
2728 EXIT();
2729 return 0;
2730}
2731
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002732#ifdef FEATURE_WLAN_TDLS
2733static int wlan_hdd_tdls_add_station(struct wiphy *wiphy,
2734 struct net_device *dev, u8 *mac, bool update, tCsrStaParams *StaParams)
2735{
2736 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2737 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2738 VOS_STATUS status;
2739
2740 ENTER();
2741
2742 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
2743 {
2744 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2745 "Invalid arguments");
2746 return -EINVAL;
2747 }
Hoonki Lee27511902013-03-14 18:19:06 -07002748
2749 if ((eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) ||
2750 (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode))
2751 {
2752 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2753 "%s: TDLS mode is disabled OR not enabled in FW."
2754 MAC_ADDRESS_STR " Request declined.",
2755 __func__, MAC_ADDR_ARRAY(mac));
2756 return -ENOTSUPP;
2757 }
2758
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002759 if (pHddCtx->isLogpInProgress)
2760 {
2761 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2762 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07002763 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002764 return -EBUSY;
2765 }
2766
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002767 /* when self is on-going, we dont' want to change link_status */
2768 if ((0 == update) && wlan_hdd_tdls_is_peer_progress(pAdapter, mac))
2769 {
2770 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2771 "%s: " MAC_ADDRESS_STR
2772 " TDLS setup is ongoing. Request declined.",
2773 __func__, MAC_ADDR_ARRAY(mac));
2774 return -EPERM;
2775 }
2776
2777 /* when others are on-going, we want to change link_status to idle */
2778 if (wlan_hdd_tdls_is_progress(pAdapter, mac, TRUE))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002779 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002780 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2781 "%s: " MAC_ADDRESS_STR
2782 " TDLS setup is ongoing. Request declined.",
2783 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002784 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002785 }
2786
2787 /* first to check if we reached to maximum supported TDLS peer.
2788 TODO: for now, return -EPERM looks working fine,
2789 but need to check if any other errno fit into this category.*/
2790 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
2791 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002792 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2793 "%s: " MAC_ADDRESS_STR
2794 " TDLS Max peer already connected. Request declined.",
2795 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002796 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002797 }
2798 else
2799 {
2800 hddTdlsPeer_t *pTdlsPeer;
2801 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac);
2802 if (pTdlsPeer && (eTDLS_LINK_CONNECTED == pTdlsPeer->link_status))
2803 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002804 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2805 "%s: " MAC_ADDRESS_STR " already connected. Request declined.",
2806 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002807 return -EPERM;
2808 }
2809 }
2810
2811 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_CONNECTING);
2812
2813 INIT_COMPLETION(pAdapter->tdls_add_station_comp);
2814
2815 if (!update)
2816 {
2817 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
2818 pAdapter->sessionId, mac);
2819 }
2820 else
2821 {
2822 status = sme_ChangeTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
2823 pAdapter->sessionId, mac, StaParams);
2824 }
2825
2826 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_add_station_comp,
2827 msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
2828
2829 if (!status)
2830 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002831 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002832 "%s: timeout waiting for tdls add station indication",
2833 __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002834 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002835 }
2836 if ( eHAL_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus)
2837 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002838 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002839 "%s: Add Station is unsucessful", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002840 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002841 }
2842
2843 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07002844
2845error:
2846 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
2847 return -EPERM;
2848
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002849}
2850#endif
2851
Jeff Johnson295189b2012-06-20 16:38:30 -07002852static int wlan_hdd_change_station(struct wiphy *wiphy,
2853 struct net_device *dev,
2854 u8 *mac,
2855 struct station_parameters *params)
2856{
2857 VOS_STATUS status = VOS_STATUS_SUCCESS;
2858 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2859 v_MACADDR_t STAMacAddress;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002860#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002861 tCsrStaParams StaParams = {0};
2862 u32 set;
2863 tANI_U8 isBufSta = 0;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002864#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07002865 ENTER();
2866
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002867 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2868 {
2869 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2870 "%s:LOGP in Progress. Ignore!!!", __func__);
2871 return -EAGAIN;
2872 }
2873
Jeff Johnson295189b2012-06-20 16:38:30 -07002874 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
2875
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002876#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002877 StaParams.capability = params->capability;
2878 StaParams.uapsd_queues = params->uapsd_queues;
2879 StaParams.max_sp = params->max_sp;
2880
2881 if (0 != params->ext_capab_len)
2882 vos_mem_copy(StaParams.extn_capability, params->ext_capab,
2883 sizeof(StaParams.extn_capability));
2884
2885 if (NULL != params->ht_capa)
2886 vos_mem_copy(&StaParams.HTCap, params->ht_capa, sizeof(tSirHTCap));
2887
2888 StaParams.supported_rates_len = params->supported_rates_len;
2889
2890 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
2891 * The supported_rates array , for all the structures propogating till Add Sta
2892 * to the firmware has to be modified , if the supplicant (ieee80211) is
2893 * modified to send more rates.
2894 */
2895
2896 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
2897 */
2898 if (StaParams.supported_rates_len > SIR_MAC_MAX_SUPP_RATES)
2899 StaParams.supported_rates_len = SIR_MAC_MAX_SUPP_RATES;
2900
2901 if (0 != StaParams.supported_rates_len) {
2902 int i = 0;
2903 vos_mem_copy(StaParams.supported_rates, params->supported_rates,
2904 StaParams.supported_rates_len);
2905 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2906 "Supported Rates with Length %d", StaParams.supported_rates_len);
2907 for (i=0; i < StaParams.supported_rates_len; i++)
2908 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2909 "[%d]: %0x", i, StaParams.supported_rates[i]);
2910 }
2911
2912 if (NULL != params->vht_capa)
2913 vos_mem_copy(&StaParams.VHTCap, params->vht_capa, sizeof(tSirVHTCap));
2914
2915 set = params->sta_flags_set;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002916#endif
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002917
2918 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2919 || (pAdapter->device_mode == WLAN_HDD_P2P_GO))
Jeff Johnson295189b2012-06-20 16:38:30 -07002920 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002921 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
Jeff Johnson295189b2012-06-20 16:38:30 -07002922 {
2923 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
2924 WLANTL_STA_AUTHENTICATED);
2925
2926 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002927 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002928 return -EINVAL;
2929 }
2930 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002931#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002932 else if (pAdapter->device_mode == WLAN_HDD_INFRA_STATION ) {
2933 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
2934 if (0 != params->ext_capab_len ) {
2935 /*Define A Macro : TODO Sunil*/
2936 if ((1<<4) & StaParams.extn_capability[3]) {
2937 isBufSta = 1;
2938 }
2939 }
2940 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2941 "%s: TDLS Peer Parameters.", __func__);
2942 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2943 "uapsd_queues: %0x\n", params->uapsd_queues);
2944 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2945 "max_sp: %0x\n", params->max_sp);
2946 if (params->ht_capa) {
2947 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2948 "ht_capa->cap_info: %0x\n", params->ht_capa->cap_info);
2949 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2950 "ht_capa->ampdu_params_info: %0x\n",
2951 params->ht_capa->ampdu_params_info);
2952 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2953 "ht_capa->extended_capabilities: %0x\n",
2954 params->ht_capa->extended_ht_cap_info);
2955 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2956 "ht_capa->tx_BF_cap_info: %0x\n",
2957 params->ht_capa->tx_BF_cap_info);
2958 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2959 "ht_capa->antenna_selection_info: %0x\n",
2960 params->ht_capa->antenna_selection_info);
2961 }
2962 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2963 "params->capability: %0x\n",params->capability);
2964 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2965 "params->ext_capab_len: %0x\n",params->ext_capab_len);
2966 if (0 != params->ext_capab_len )
2967 {
2968 int i =0;
2969 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2970 "Extended capabilities:");
2971 for (i=0; i < params->ext_capab_len; i++)
2972 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2973 "[%d]: %0x", i, params->ext_capab[i]);
2974 }
2975 //status = wlan_hdd_tdls_set_peer_caps( mac, params->uapsd_queues,
2976 // params->max_sp, isBufSta);
2977 if (VOS_STATUS_SUCCESS != status) {
2978 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2979 "%s: wlan_hdd_tdls_set_peer_caps failed!", __func__);
2980 return -EINVAL;
2981 }
2982 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2983 "ht_capa->cap_info: %0x\n", StaParams.HTCap.capInfo);
2984 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 1, &StaParams);
2985
2986 if (VOS_STATUS_SUCCESS != status) {
2987 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2988 "%s: sme_ChangeTdlsPeerSta failed!", __func__);
2989 return -EINVAL;
2990 }
2991 }
2992 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002993#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002994
Jeff Johnsone7245742012-09-05 17:12:55 -07002995 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002996 return status;
2997}
2998
2999/*
3000 * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
3001 * This function is used to get peer station index in IBSS mode
3002 */
3003static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
3004{
3005 u8 idx = 0;
3006 u8 temp[VOS_MAC_ADDR_SIZE] = {0};
3007 ENTER();
3008 memset(temp, 0, VOS_MAC_ADDR_SIZE);
3009 for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
3010 {
3011 if ( (0 !=
3012 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
3013 && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
3014 temp, VOS_MAC_ADDR_SIZE)
3015 )
3016 {
3017 return idx;
3018 }
3019 }
3020 return idx;
3021}
3022
3023
3024/*
3025 * FUNCTION: wlan_hdd_cfg80211_add_key
3026 * This function is used to initialize the key information
3027 */
3028#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003029static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003030 struct net_device *ndev,
3031 u8 key_index, bool pairwise,
3032 const u8 *mac_addr,
3033 struct key_params *params
3034 )
3035#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003036static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003037 struct net_device *ndev,
3038 u8 key_index, const u8 *mac_addr,
3039 struct key_params *params
3040 )
3041#endif
3042{
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003043 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003044 tCsrRoamSetKey setKey;
3045 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3046 int status = 0;
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003047 v_U32_t roamId= 0xFF;
3048 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003049 hdd_hostapd_state_t *pHostapdState;
3050 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003051 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07003052
3053 ENTER();
3054
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003055 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3056 {
3057 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3058 "%s:LOGP in Progress. Ignore!!!", __func__);
3059 return -EAGAIN;
3060 }
3061
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003062 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
3063 __func__, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003064
3065 if (CSR_MAX_NUM_KEY <= key_index)
3066 {
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003067 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003068 key_index);
3069
3070 return -EINVAL;
3071 }
3072
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003073 if (CSR_MAX_KEY_LEN < params->key_len)
3074 {
3075 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key length %d", __func__,
3076 params->key_len);
3077
3078 return -EINVAL;
3079 }
3080
3081 hddLog(VOS_TRACE_LEVEL_INFO,
3082 "%s: called with key index = %d & key length %d",
3083 __func__, key_index, params->key_len);
Jeff Johnson295189b2012-06-20 16:38:30 -07003084
3085 /*extract key idx, key len and key*/
3086 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3087 setKey.keyId = key_index;
3088 setKey.keyLength = params->key_len;
3089 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
3090
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003091 switch (params->cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07003092 {
3093 case WLAN_CIPHER_SUITE_WEP40:
3094 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
3095 break;
3096
3097 case WLAN_CIPHER_SUITE_WEP104:
3098 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
3099 break;
3100
3101 case WLAN_CIPHER_SUITE_TKIP:
3102 {
3103 u8 *pKey = &setKey.Key[0];
3104 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
3105
3106 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
3107
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003108 /*Supplicant sends the 32bytes key in this order
Jeff Johnson295189b2012-06-20 16:38:30 -07003109
3110 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003111 | Tk1 |TX-MIC | RX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003112 |--------------|----------|----------|
3113 <---16bytes---><--8bytes--><--8bytes-->
3114
3115 */
3116 /*Sme expects the 32 bytes key to be in the below order
3117
3118 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003119 | Tk1 |RX-MIC | TX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003120 |--------------|----------|----------|
3121 <---16bytes---><--8bytes--><--8bytes-->
3122 */
3123 /* Copy the Temporal Key 1 (TK1) */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003124 vos_mem_copy(pKey, params->key, 16);
Jeff Johnson295189b2012-06-20 16:38:30 -07003125
3126 /*Copy the rx mic first*/
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003127 vos_mem_copy(&pKey[16], &params->key[24], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003128
3129 /*Copy the tx mic */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003130 vos_mem_copy(&pKey[24], &params->key[16], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003131
3132
3133 break;
3134 }
3135
3136 case WLAN_CIPHER_SUITE_CCMP:
3137 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
3138 break;
3139
3140#ifdef FEATURE_WLAN_WAPI
3141 case WLAN_CIPHER_SUITE_SMS4:
3142 {
3143 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3144 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
3145 params->key, params->key_len);
3146 return 0;
3147 }
3148#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003149
Jeff Johnson295189b2012-06-20 16:38:30 -07003150#ifdef FEATURE_WLAN_CCX
3151 case WLAN_CIPHER_SUITE_KRK:
3152 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
3153 break;
3154#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003155
3156#ifdef WLAN_FEATURE_11W
3157 case WLAN_CIPHER_SUITE_AES_CMAC:
3158 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
3159 /* Temporarily we will ignore the setting of the IGTK. Once the Riva
3160 firmware is modified to handle the IGTK, then we will proceeed normally.
3161 For now, we just return success. */
3162 return 0;
3163 /* break; */
3164#endif
3165
Jeff Johnson295189b2012-06-20 16:38:30 -07003166 default:
3167 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
3168 __func__, params->cipher);
3169 return -EOPNOTSUPP;
3170 }
3171
3172 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
3173 __func__, setKey.encType);
3174
3175
3176
3177 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003178 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07003179 )
3180 {
3181
3182
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003183 if (
Jeff Johnson295189b2012-06-20 16:38:30 -07003184#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3185 (!pairwise)
3186#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003187 (!mac_addr || is_broadcast_ether_addr(mac_addr))
Jeff Johnson295189b2012-06-20 16:38:30 -07003188#endif
3189 )
3190 {
3191 /* set group key*/
3192 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson1250df42012-12-10 14:31:52 -08003193 "%s- %d: setting Broadcast key",
Jeff Johnson295189b2012-06-20 16:38:30 -07003194 __func__, __LINE__);
3195 setKey.keyDirection = eSIR_RX_ONLY;
3196 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3197 }
3198 else
3199 {
3200 /* set pairwise key*/
3201 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3202 "%s- %d: setting pairwise key",
3203 __func__, __LINE__);
3204 setKey.keyDirection = eSIR_TX_RX;
3205 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3206 }
3207
3208 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003209 if( pHostapdState->bssState == BSS_START )
3210 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003211 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3212
3213 if ( status != eHAL_STATUS_SUCCESS )
3214 {
3215 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3216 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3217 __LINE__, status );
3218 }
3219 }
3220
3221 /* Saving WEP keys */
3222 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
3223 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
3224 {
3225 //Save the wep key in ap context. Issue setkey after the BSS is started.
3226 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3227 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
3228 }
3229 else
3230 {
3231 //Save the key in ap context. Issue setkey after the BSS is started.
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003232 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003233 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
3234 }
3235 }
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003236 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
3237 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) )
Jeff Johnson295189b2012-06-20 16:38:30 -07003238 {
3239 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3240 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3241
3242 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
3243
Venkata Prathyusha Kuntupalliee2ce712013-01-17 14:09:24 -08003244 pWextState->roamProfile.Keys.defaultIndex = key_index;
3245
3246
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003247 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07003248 params->key, params->key_len);
3249
3250 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3251
3252 if (!( ( IW_AUTH_KEY_MGMT_802_1X
3253 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
3254 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3255 )
3256 &&
3257 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3258 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3259 )
3260 )
3261 {
3262 /* in case of static WEP, macaddr/bssid is not coming from nl80211
3263 * interface, copy bssid for pairwise key and group macaddr for
3264 * group key initialization*/
3265
3266 tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
3267
3268 pWextState->roamProfile.negotiatedUCEncryptionType =
3269 pHddStaCtx->conn_info.ucEncryptionType =
3270 ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
3271 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
3272 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
3273
3274
3275 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3276 "%s: Negotiated encryption type %d", __func__,
3277 pWextState->roamProfile.negotiatedUCEncryptionType);
3278
3279 sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
3280 &pWextState->roamProfile, true);
3281 setKey.keyLength = 0;
3282 setKey.keyDirection = eSIR_TX_RX;
3283
3284#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3285 if (pairwise)
3286 {
3287#endif
3288 if (mac_addr)
3289 {
3290 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3291 }
3292 else
3293 {
3294 /* macaddr is NULL, set the peerMac to bssId in case of BSS,
3295 * and peerMacAddress in case of IBSS*/
3296 if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
3297 {
3298 u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
3299 if (HDD_MAX_NUM_IBSS_STA != staidx)
3300 {
3301 vos_mem_copy(setKey.peerMac,
3302 &pHddStaCtx->conn_info.peerMacAddress[staidx],
3303 WNI_CFG_BSSID_LEN);
3304
3305 }
3306 else
3307 {
3308 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
3309 __func__);
3310 return -EOPNOTSUPP;
3311 }
3312 }
3313 else
3314 {
3315 vos_mem_copy(setKey.peerMac,
3316 &pHddStaCtx->conn_info.bssId[0],
3317 WNI_CFG_BSSID_LEN);
3318 }
3319 }
3320#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3321 }
3322 else
3323 {
3324 /* set group key*/
3325 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3326 "%s- %d: setting Group key",
3327 __func__, __LINE__);
3328 setKey.keyDirection = eSIR_RX_ONLY;
3329 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3330 }
3331#endif
3332 }
3333 else if (
3334#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3335 (!pairwise)
3336#else
3337 (!mac_addr || is_broadcast_ether_addr(mac_addr))
3338#endif
3339 )
3340 {
3341 /* set group key*/
3342 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3343 "%s- %d: setting Group key",
3344 __func__, __LINE__);
3345 setKey.keyDirection = eSIR_RX_ONLY;
3346 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3347 }
3348 else
3349 {
3350 /* set pairwise key*/
3351 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3352 "%s- %d: setting pairwise key",
3353 __func__, __LINE__);
3354 setKey.keyDirection = eSIR_TX_RX;
3355 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3356 }
3357
3358 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3359 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3360 __func__, setKey.peerMac[0], setKey.peerMac[1],
3361 setKey.peerMac[2], setKey.peerMac[3],
3362 setKey.peerMac[4], setKey.peerMac[5],
3363 setKey.keyDirection);
3364
3365 vos_status = wlan_hdd_check_ula_done(pAdapter);
3366
3367 if ( vos_status != VOS_STATUS_SUCCESS )
3368 {
3369 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3370 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
3371 __LINE__, vos_status );
3372
3373 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3374
3375 return -EINVAL;
3376
3377 }
3378
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003379#ifdef WLAN_FEATURE_VOWIFI_11R
3380 /* The supplicant may attempt to set the PTK once pre-authentication is done.
3381 Save the key in the UMAC and include it in the ADD BSS request */
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003382 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303383 if( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_WAIT )
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003384 {
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303385 return -EINVAL;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003386 }
3387#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07003388
3389 /* issue set key request to SME*/
3390 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3391 pAdapter->sessionId, &setKey, &roamId );
3392
3393 if ( 0 != status )
3394 {
3395 hddLog(VOS_TRACE_LEVEL_ERROR,
3396 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3397 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3398 return -EINVAL;
3399 }
3400
3401
3402 /* in case of IBSS as there was no information available about WEP keys during
3403 * IBSS join, group key intialized with NULL key, so re-initialize group key
3404 * with correct value*/
3405 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
3406 !( ( IW_AUTH_KEY_MGMT_802_1X
3407 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
3408 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3409 )
3410 &&
3411 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3412 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3413 )
3414 )
3415 {
3416 setKey.keyDirection = eSIR_RX_ONLY;
3417 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3418
3419 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3420 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3421 __func__, setKey.peerMac[0], setKey.peerMac[1],
3422 setKey.peerMac[2], setKey.peerMac[3],
3423 setKey.peerMac[4], setKey.peerMac[5],
3424 setKey.keyDirection);
3425
3426 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3427 pAdapter->sessionId, &setKey, &roamId );
3428
3429 if ( 0 != status )
3430 {
3431 hddLog(VOS_TRACE_LEVEL_ERROR,
3432 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
3433 __func__, status);
3434 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3435 return -EINVAL;
3436 }
3437 }
3438 }
3439
3440 return 0;
3441}
3442
3443/*
3444 * FUNCTION: wlan_hdd_cfg80211_get_key
3445 * This function is used to get the key information
3446 */
3447#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3448static int wlan_hdd_cfg80211_get_key(
3449 struct wiphy *wiphy,
3450 struct net_device *ndev,
3451 u8 key_index, bool pairwise,
3452 const u8 *mac_addr, void *cookie,
3453 void (*callback)(void *cookie, struct key_params*)
3454 )
3455#else
3456static int wlan_hdd_cfg80211_get_key(
3457 struct wiphy *wiphy,
3458 struct net_device *ndev,
3459 u8 key_index, const u8 *mac_addr, void *cookie,
3460 void (*callback)(void *cookie, struct key_params*)
3461 )
3462#endif
3463{
3464 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3465 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3466 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
3467 struct key_params params;
3468
3469 ENTER();
3470
3471 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3472 __func__,pAdapter->device_mode);
3473
3474 memset(&params, 0, sizeof(params));
3475
3476 if (CSR_MAX_NUM_KEY <= key_index)
3477 {
3478 return -EINVAL;
3479 }
3480
3481 switch(pRoamProfile->EncryptionType.encryptionType[0])
3482 {
3483 case eCSR_ENCRYPT_TYPE_NONE:
3484 params.cipher = IW_AUTH_CIPHER_NONE;
3485 break;
3486
3487 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3488 case eCSR_ENCRYPT_TYPE_WEP40:
3489 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3490 break;
3491
3492 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3493 case eCSR_ENCRYPT_TYPE_WEP104:
3494 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3495 break;
3496
3497 case eCSR_ENCRYPT_TYPE_TKIP:
3498 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3499 break;
3500
3501 case eCSR_ENCRYPT_TYPE_AES:
3502 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3503 break;
3504
3505 default:
3506 params.cipher = IW_AUTH_CIPHER_NONE;
3507 break;
3508 }
3509
3510 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3511 params.seq_len = 0;
3512 params.seq = NULL;
3513 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3514 callback(cookie, &params);
3515 return 0;
3516}
3517
3518/*
3519 * FUNCTION: wlan_hdd_cfg80211_del_key
3520 * This function is used to delete the key information
3521 */
3522#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3523static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3524 struct net_device *ndev,
3525 u8 key_index,
3526 bool pairwise,
3527 const u8 *mac_addr
3528 )
3529#else
3530static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3531 struct net_device *ndev,
3532 u8 key_index,
3533 const u8 *mac_addr
3534 )
3535#endif
3536{
3537 int status = 0;
3538
3539 //This code needs to be revisited. There is sme_removeKey API, we should
3540 //plan to use that. After the change to use correct index in setkey,
3541 //it is observed that this is invalidating peer
3542 //key index whenever re-key is done. This is affecting data link.
3543 //It should be ok to ignore del_key.
3544#if 0
3545 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3546 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
3547 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3548 tCsrRoamSetKey setKey;
3549 v_U32_t roamId= 0xFF;
3550
3551 ENTER();
3552
3553 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3554 __func__,pAdapter->device_mode);
3555
3556 if (CSR_MAX_NUM_KEY <= key_index)
3557 {
3558 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3559 key_index);
3560
3561 return -EINVAL;
3562 }
3563
3564 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3565 setKey.keyId = key_index;
3566
3567 if (mac_addr)
3568 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3569 else
3570 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3571
3572 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3573
3574 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003575 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07003576 )
3577 {
3578
3579 hdd_hostapd_state_t *pHostapdState =
3580 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3581 if( pHostapdState->bssState == BSS_START)
3582 {
3583 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3584
3585 if ( status != eHAL_STATUS_SUCCESS )
3586 {
3587 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3588 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3589 __LINE__, status );
3590 }
3591 }
3592 }
3593 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003594 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003595 )
3596 {
3597 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3598
3599 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3600
3601 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3602 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
3603 __func__, setKey.peerMac[0], setKey.peerMac[1],
3604 setKey.peerMac[2], setKey.peerMac[3],
3605 setKey.peerMac[4], setKey.peerMac[5]);
3606 if(pAdapter->sessionCtx.station.conn_info.connState ==
3607 eConnectionState_Associated)
3608 {
3609 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3610 pAdapter->sessionId, &setKey, &roamId );
3611
3612 if ( 0 != status )
3613 {
3614 hddLog(VOS_TRACE_LEVEL_ERROR,
3615 "%s: sme_RoamSetKey failure, returned %d",
3616 __func__, status);
3617 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3618 return -EINVAL;
3619 }
3620 }
3621 }
3622#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003623 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003624 return status;
3625}
3626
3627/*
3628 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3629 * This function is used to set the default tx key index
3630 */
3631#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3632static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3633 struct net_device *ndev,
3634 u8 key_index,
3635 bool unicast, bool multicast)
3636#else
3637static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3638 struct net_device *ndev,
3639 u8 key_index)
3640#endif
3641{
3642 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3643 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3644 int status = 0;
3645 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3646
3647 ENTER();
3648
3649 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3650 __func__,pAdapter->device_mode, key_index);
3651
3652 if (CSR_MAX_NUM_KEY <= key_index)
3653 {
3654 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3655 key_index);
3656
3657 return -EINVAL;
3658 }
3659
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003660 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3661 {
3662 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3663 "%s:LOGP in Progress. Ignore!!!", __func__);
3664 return -EAGAIN;
3665 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003666
3667 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003668 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003669 )
3670 {
3671 if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
3672 (eCSR_ENCRYPT_TYPE_TKIP !=
3673 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3674 (eCSR_ENCRYPT_TYPE_AES !=
3675 pWextState->roamProfile.EncryptionType.encryptionType[0])
3676 )
3677 {
3678 /* if default key index is not same as previous one,
3679 * then update the default key index */
3680
3681 tCsrRoamSetKey setKey;
3682 v_U32_t roamId= 0xFF;
3683 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
3684
3685 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
3686 __func__, key_index);
3687
3688 Keys->defaultIndex = (u8)key_index;
3689 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3690 setKey.keyId = key_index;
3691 setKey.keyLength = Keys->KeyLength[key_index];
3692
3693 vos_mem_copy(&setKey.Key[0],
3694 &Keys->KeyMaterial[key_index][0],
3695 Keys->KeyLength[key_index]);
3696
3697 setKey.keyDirection = eSIR_TX_ONLY;
3698
3699 vos_mem_copy(setKey.peerMac,
3700 &pHddStaCtx->conn_info.bssId[0],
3701 WNI_CFG_BSSID_LEN);
3702
3703 setKey.encType =
3704 pWextState->roamProfile.EncryptionType.encryptionType[0];
3705
3706 /* issue set key request */
3707 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3708 pAdapter->sessionId, &setKey, &roamId );
3709
3710 if ( 0 != status )
3711 {
3712 hddLog(VOS_TRACE_LEVEL_ERROR,
3713 "%s: sme_RoamSetKey failed, returned %d", __func__,
3714 status);
3715 return -EINVAL;
3716 }
3717 }
3718 }
3719
3720 /* In SoftAp mode setting key direction for default mode */
3721 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3722 {
3723 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3724 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3725 (eCSR_ENCRYPT_TYPE_AES !=
3726 pWextState->roamProfile.EncryptionType.encryptionType[0])
3727 )
3728 {
3729 /* Saving key direction for default key index to TX default */
3730 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3731 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3732 }
3733 }
3734
3735 return status;
3736}
3737
Jeff Johnson295189b2012-06-20 16:38:30 -07003738/*
3739 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3740 * This function is used to inform the BSS details to nl80211 interface.
3741 */
3742static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3743 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3744{
3745 struct net_device *dev = pAdapter->dev;
3746 struct wireless_dev *wdev = dev->ieee80211_ptr;
3747 struct wiphy *wiphy = wdev->wiphy;
3748 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3749 int chan_no;
3750 int ie_length;
3751 const char *ie;
3752 unsigned int freq;
3753 struct ieee80211_channel *chan;
3754 int rssi = 0;
3755 struct cfg80211_bss *bss = NULL;
3756
3757 ENTER();
3758
3759 if( NULL == pBssDesc )
3760 {
3761 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3762 return bss;
3763 }
3764
3765 chan_no = pBssDesc->channelId;
3766 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3767 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3768
3769 if( NULL == ie )
3770 {
3771 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3772 return bss;
3773 }
3774
3775#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3776 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3777 {
3778 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3779 }
3780 else
3781 {
3782 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3783 }
3784#else
3785 freq = ieee80211_channel_to_frequency(chan_no);
3786#endif
3787
3788 chan = __ieee80211_get_channel(wiphy, freq);
3789
3790 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3791 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3792 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3793 if (bss == NULL)
3794 {
3795 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3796
3797 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3798 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3799 pBssDesc->capabilityInfo,
3800 pBssDesc->beaconInterval, ie, ie_length,
3801 rssi, GFP_KERNEL ));
3802}
3803 else
3804 {
3805 return bss;
3806 }
3807}
3808
3809
3810
3811/*
3812 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3813 * This function is used to inform the BSS details to nl80211 interface.
3814 */
3815struct cfg80211_bss*
3816wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3817 tSirBssDescription *bss_desc
3818 )
3819{
3820 /*
3821 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3822 already exists in bss data base of cfg80211 for that particular BSS ID.
3823 Using cfg80211_inform_bss_frame to update the bss entry instead of
3824 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3825 now there is no possibility to get the mgmt(probe response) frame from PE,
3826 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3827 cfg80211_inform_bss_frame.
3828 */
3829 struct net_device *dev = pAdapter->dev;
3830 struct wireless_dev *wdev = dev->ieee80211_ptr;
3831 struct wiphy *wiphy = wdev->wiphy;
3832 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003833#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3834 qcom_ie_age *qie_age = NULL;
3835 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3836#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003837 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003838#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003839 const char *ie =
3840 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3841 unsigned int freq;
3842 struct ieee80211_channel *chan;
3843 struct ieee80211_mgmt *mgmt =
3844 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3845 struct cfg80211_bss *bss_status = NULL;
3846 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3847 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003848#ifdef WLAN_OPEN_SOURCE
3849 struct timespec ts;
3850#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003851
3852 ENTER();
3853
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003854 if (!mgmt)
3855 return NULL;
3856
Jeff Johnson295189b2012-06-20 16:38:30 -07003857 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003858
3859#ifdef WLAN_OPEN_SOURCE
3860 /* Android does not want the timestamp from the frame.
3861 Instead it wants a monotonic increasing value */
3862 get_monotonic_boottime(&ts);
3863 mgmt->u.probe_resp.timestamp =
3864 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3865#else
3866 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003867 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3868 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003869
3870#endif
3871
Jeff Johnson295189b2012-06-20 16:38:30 -07003872 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3873 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003874
3875#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3876 /* GPS Requirement: need age ie per entry. Using vendor specific. */
3877 /* Assuming this is the last IE, copy at the end */
3878 ie_length -=sizeof(qcom_ie_age);
3879 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
3880 qie_age->element_id = QCOM_VENDOR_IE_ID;
3881 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
3882 qie_age->oui_1 = QCOM_OUI1;
3883 qie_age->oui_2 = QCOM_OUI2;
3884 qie_age->oui_3 = QCOM_OUI3;
3885 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
3886 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
3887#endif
3888
Jeff Johnson295189b2012-06-20 16:38:30 -07003889 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3890
3891 mgmt->frame_control |=
3892 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3893
3894#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3895 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3896 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3897 {
3898 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3899 }
3900 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3901 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3902
3903 {
3904 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3905 }
3906 else
3907 {
3908 kfree(mgmt);
3909 return NULL;
3910 }
3911#else
3912 freq = ieee80211_channel_to_frequency(chan_no);
3913#endif
3914 chan = __ieee80211_get_channel(wiphy, freq);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08003915 /*when the band is changed on the fly using the GUI, three things are done
3916 * 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)
3917 * as part of the scan abort, message willbe queued to PE and we proceed with flushing and changinh the band.
3918 * pe will stop the scanning further and report back the results what ever it had till now by calling the call back function.
3919 * if the time between update band and scandone call back is sufficent enough the band change reflects in SME, SME validates the channels
3920 * and discards the channels correponding to previous band and calls back with zero bss results.
3921 * 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
3922 * all the channels correponding to previous band.this is due to race condition.but those channels are invalid to the new band and so
3923 * this function __ieee80211_get_channel will return NULL.Each time we report scan result with this pointer null warning kernel trace is printed.
3924 * if the scan results contain large number of APs continuosly kernel warning trace is printed and it will lead to apps watch dog bark.
3925 * So drop the bss and continue to next bss.
3926 */
3927 if(chan == NULL)
3928 {
3929 hddLog(VOS_TRACE_LEVEL_INFO, "%s chan pointer is NULL", __func__);
3930 return NULL;
3931 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003932 /*To keep the rssi icon of the connected AP in the scan window
3933 *and the rssi icon of the wireless networks in sync
3934 * */
3935 if (( eConnectionState_Associated ==
3936 pAdapter->sessionCtx.station.conn_info.connState ) &&
3937 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3938 pAdapter->sessionCtx.station.conn_info.bssId,
3939 WNI_CFG_BSSID_LEN)))
3940 {
3941 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3942 rssi = (pAdapter->rssi * 100);
3943 }
3944 else
3945 {
3946 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3947 }
3948
3949 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3950 frame_len, rssi, GFP_KERNEL);
3951 kfree(mgmt);
3952 return bss_status;
3953}
3954
3955/*
3956 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3957 * This function is used to update the BSS data base of CFG8011
3958 */
3959struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3960 tCsrRoamInfo *pRoamInfo
3961 )
3962{
3963 tCsrRoamConnectedProfile roamProfile;
3964 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3965 struct cfg80211_bss *bss = NULL;
3966
3967 ENTER();
3968
3969 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
3970 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
3971
3972 if (NULL != roamProfile.pBssDesc)
3973 {
3974 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
3975 &roamProfile);
3976
3977 if (NULL == bss)
3978 {
3979 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
3980 __func__);
3981 }
3982
3983 sme_RoamFreeConnectProfile(hHal, &roamProfile);
3984 }
3985 else
3986 {
3987 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
3988 __func__);
3989 }
3990 return bss;
3991}
3992
3993/*
3994 * FUNCTION: wlan_hdd_cfg80211_update_bss
3995 */
3996static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
3997 hdd_adapter_t *pAdapter
3998 )
3999{
4000 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4001 tCsrScanResultInfo *pScanResult;
4002 eHalStatus status = 0;
4003 tScanResultHandle pResult;
4004 struct cfg80211_bss *bss_status = NULL;
4005
4006 ENTER();
4007
4008 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4009 {
4010 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
4011 return -EAGAIN;
4012 }
4013
4014 /*
4015 * start getting scan results and populate cgf80211 BSS database
4016 */
4017 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
4018
4019 /* no scan results */
4020 if (NULL == pResult)
4021 {
4022 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
4023 return status;
4024 }
4025
4026 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
4027
4028 while (pScanResult)
4029 {
4030 /*
4031 * cfg80211_inform_bss() is not updating ie field of bss entry, if
4032 * entry already exists in bss data base of cfg80211 for that
4033 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
4034 * bss entry instead of cfg80211_inform_bss, But this call expects
4035 * mgmt packet as input. As of now there is no possibility to get
4036 * the mgmt(probe response) frame from PE, converting bss_desc to
4037 * ieee80211_mgmt(probe response) and passing to c
4038 * fg80211_inform_bss_frame.
4039 * */
4040
4041 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
4042 &pScanResult->BssDescriptor);
4043
4044
4045 if (NULL == bss_status)
4046 {
4047 hddLog(VOS_TRACE_LEVEL_INFO,
4048 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
4049 }
4050 else
4051 {
4052 cfg80211_put_bss(bss_status);
4053 }
4054
4055 pScanResult = sme_ScanResultGetNext(hHal, pResult);
4056 }
4057
4058 sme_ScanResultPurge(hHal, pResult);
4059
4060 return 0;
4061}
4062
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004063void
4064hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
4065{
4066 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004067 "%02X:%02X:%02X:%02X:%02X:%02X\n",
4068 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
4069 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004070} /****** end hddPrintMacAddr() ******/
4071
4072void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004073hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004074{
4075 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004076 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
4077 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
4078 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
4079 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004080} /****** end hddPrintPmkId() ******/
4081
4082//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
4083//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
4084
4085//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
4086//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
4087
4088#define dump_bssid(bssid) \
4089 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004090 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
4091 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
4092 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004093 }
4094
4095#define dump_pmkid(pMac, pmkid) \
4096 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004097 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
4098 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
4099 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004100 }
4101
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07004102#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004103/*
4104 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
4105 * This function is used to notify the supplicant of a new PMKSA candidate.
4106 */
4107int wlan_hdd_cfg80211_pmksa_candidate_notify(
4108 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
4109 int index, bool preauth )
4110{
Jeff Johnsone7245742012-09-05 17:12:55 -07004111#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004112 struct net_device *dev = pAdapter->dev;
4113
4114 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07004115 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004116
4117 if( NULL == pRoamInfo )
4118 {
4119 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
4120 return -EINVAL;
4121 }
4122
4123 dump_bssid(pRoamInfo->bssid);
4124 cfg80211_pmksa_candidate_notify(dev, index,
4125 pRoamInfo->bssid, preauth, GFP_KERNEL);
Jeff Johnsone7245742012-09-05 17:12:55 -07004126#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004127 return 0;
4128}
4129#endif //FEATURE_WLAN_LFR
4130
Jeff Johnson295189b2012-06-20 16:38:30 -07004131/*
4132 * FUNCTION: hdd_cfg80211_scan_done_callback
4133 * scanning callback function, called after finishing scan
4134 *
4135 */
4136static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
4137 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
4138{
4139 struct net_device *dev = (struct net_device *) pContext;
4140 //struct wireless_dev *wdev = dev->ieee80211_ptr;
4141 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004142 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4143 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004144 struct cfg80211_scan_request *req = NULL;
4145 int ret = 0;
4146
4147 ENTER();
4148
4149 hddLog(VOS_TRACE_LEVEL_INFO,
4150 "%s called with halHandle = %p, pContext = %p,"
4151 "scanID = %d, returned status = %d\n",
4152 __func__, halHandle, pContext, (int) scanId, (int) status);
4153
4154 //Block on scan req completion variable. Can't wait forever though.
4155 ret = wait_for_completion_interruptible_timeout(
4156 &pScanInfo->scan_req_completion_event,
4157 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
4158 if (!ret)
4159 {
4160 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004161 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004162 }
4163
4164 if(pScanInfo->mScanPending != VOS_TRUE)
4165 {
4166 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004167 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004168 }
4169
4170 /* Check the scanId */
4171 if (pScanInfo->scanId != scanId)
4172 {
4173 hddLog(VOS_TRACE_LEVEL_INFO,
4174 "%s called with mismatched scanId pScanInfo->scanId = %d "
4175 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
4176 (int) scanId);
4177 }
4178
Jeff Johnson295189b2012-06-20 16:38:30 -07004179 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
4180 pAdapter);
4181
4182 if (0 > ret)
4183 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
4184
4185
4186 /* If any client wait scan result through WEXT
4187 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004188 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07004189 {
4190 /* The other scan request waiting for current scan finish
4191 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004192 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004193 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004194 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004195 }
4196 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004197 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004198 {
4199 struct net_device *dev = pAdapter->dev;
4200 union iwreq_data wrqu;
4201 int we_event;
4202 char *msg;
4203
4204 memset(&wrqu, '\0', sizeof(wrqu));
4205 we_event = SIOCGIWSCAN;
4206 msg = NULL;
4207 wireless_send_event(dev, we_event, &wrqu, msg);
4208 }
4209 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004210 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004211
4212 /* Get the Scan Req */
4213 req = pAdapter->request;
4214
4215 if (!req)
4216 {
4217 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004218 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07004219 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004220 }
4221
4222 /*
4223 * setting up 0, just in case.
4224 */
4225 req->n_ssids = 0;
4226 req->n_channels = 0;
4227 req->ie = 0;
4228
Jeff Johnson295189b2012-06-20 16:38:30 -07004229 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004230 /* Scan is no longer pending */
4231 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004232
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07004233 /*
4234 * cfg80211_scan_done informing NL80211 about completion
4235 * of scanning
4236 */
4237 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004238 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004239
Jeff Johnsone7245742012-09-05 17:12:55 -07004240allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004241 /* release the wake lock at the end of the scan*/
4242 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004243
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004244 /* Acquire wakelock to handle the case where APP's tries to suspend
4245 * immediatly after the driver gets connect request(i.e after scan)
4246 * from supplicant, this result in app's is suspending and not able
4247 * to process the connect request to AP */
4248 hdd_allow_suspend_timeout(100);
4249
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004250#ifdef FEATURE_WLAN_TDLS
4251 wlan_hdd_tdls_scan_done_callback(pAdapter);
4252#endif
4253
Jeff Johnson295189b2012-06-20 16:38:30 -07004254 EXIT();
4255 return 0;
4256}
4257
4258/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004259 * FUNCTION: hdd_isScanAllowed
4260 * Go through each adapter and check if scan allowed
4261 *
4262 */
4263v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
4264{
4265 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4266 hdd_station_ctx_t *pHddStaCtx = NULL;
4267 hdd_adapter_t *pAdapter = NULL;
4268 VOS_STATUS status = 0;
4269 v_U8_t staId = 0;
4270 v_U8_t *staMac = NULL;
4271
4272 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4273
4274 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4275 {
4276 pAdapter = pAdapterNode->pAdapter;
4277
4278 if( pAdapter )
4279 {
4280 hddLog(VOS_TRACE_LEVEL_INFO,
4281 "%s: Adapter with device mode %d exists",
4282 __func__, pAdapter->device_mode);
4283 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4284 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4285 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
4286 {
4287 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4288 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
4289 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
4290 {
4291 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
4292 hddLog(VOS_TRACE_LEVEL_ERROR,
4293 "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the "
4294 "middle of WPS/EAPOL exchange.", __func__,
4295 staMac[0], staMac[1], staMac[2],
4296 staMac[3], staMac[4], staMac[5]);
4297 return VOS_FALSE;
4298 }
4299 }
4300 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
4301 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
4302 {
4303 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
4304 {
4305 if ((pAdapter->aStaInfo[staId].isUsed) &&
4306 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
4307 {
4308 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
4309
4310 hddLog(VOS_TRACE_LEVEL_ERROR,
4311 "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the "
4312 "middle of WPS/EAPOL exchange.", __func__,
4313 staMac[0], staMac[1], staMac[2],
4314 staMac[3], staMac[4], staMac[5]);
4315 return VOS_FALSE;
4316 }
4317 }
4318 }
4319 }
4320 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4321 pAdapterNode = pNext;
4322 }
4323 hddLog(VOS_TRACE_LEVEL_INFO,
4324 "%s: Scan allowed", __func__);
4325 return VOS_TRUE;
4326}
4327
4328/*
Jeff Johnson295189b2012-06-20 16:38:30 -07004329 * FUNCTION: wlan_hdd_cfg80211_scan
4330 * this scan respond to scan trigger and update cfg80211 scan database
4331 * later, scan dump command can be used to recieve scan results
4332 */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08004333int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
4334#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4335 struct net_device *dev,
4336#endif
4337 struct cfg80211_scan_request *request)
4338{
4339#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4340 struct net_device *dev = request->wdev->netdev;
4341#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004342 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4343 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4344 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4345 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
4346 tCsrScanRequest scanRequest;
4347 tANI_U8 *channelList = NULL, i;
4348 v_U32_t scanId = 0;
4349 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004350 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004351 v_U8_t* pP2pIe = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004352
4353 ENTER();
4354
4355 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4356 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004357
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004358 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004359 (eConnectionState_Connecting ==
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004360 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004361 {
4362 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004363 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
4364 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004365 return -EBUSY;
4366 }
4367
Jeff Johnson295189b2012-06-20 16:38:30 -07004368#ifdef WLAN_BTAMP_FEATURE
4369 //Scan not supported when AMP traffic is on.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004370 if (VOS_TRUE == WLANBAP_AmpSessionOn())
Jeff Johnson295189b2012-06-20 16:38:30 -07004371 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004372 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004373 "%s: No scanning when AMP is on", __func__);
4374 return -EOPNOTSUPP;
4375 }
4376#endif
4377 //Scan on any other interface is not supported.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004378 if (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07004379 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004380 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004381 "%s: Not scanning on device_mode = %d",
4382 __func__, pAdapter->device_mode);
4383 return -EOPNOTSUPP;
4384 }
4385
4386 if (TRUE == pScanInfo->mScanPending)
4387 {
4388 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004389 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07004390 }
4391
4392 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4393 {
4394 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4395 "%s:LOGP in Progress. Ignore!!!", __func__);
4396 return -EAGAIN;
4397 }
4398
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07004399 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
4400 {
4401 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4402 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
4403 return -EAGAIN;
4404 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004405 //Don't Allow Scan and return busy if Remain On
4406 //Channel and action frame is pending
4407 //Otherwise Cancel Remain On Channel and allow Scan
4408 //If no action frame pending
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004409 if (0 != wlan_hdd_check_remain_on_channel(pAdapter))
Jeff Johnson32d95a32012-09-10 13:15:23 -07004410 {
4411 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
4412 return -EBUSY;
4413 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004414#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004415 /* if tdls disagree scan right now, return immediately.
4416 tdls will schedule the scan when scan is allowed. (return SUCCESS)
4417 or will reject the scan if any TDLS is in progress. (return -EBUSY)
4418 */
4419 status = wlan_hdd_tdls_scan_callback (pAdapter,
4420 wiphy,
4421#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4422 dev,
Gopichand Nakkalac3c42b92013-03-20 19:42:34 -07004423#endif
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004424 request);
4425 if(status <= 0)
4426 {
4427 hddLog(VOS_TRACE_LEVEL_INFO, "%s: TDLS Pending %d", __func__, status);
4428 return status;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004429 }
4430#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07004431
Jeff Johnson295189b2012-06-20 16:38:30 -07004432 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
4433 {
4434 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08004435 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004436 return -EAGAIN;
4437 }
4438 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
4439 {
4440 hddLog(VOS_TRACE_LEVEL_WARN,
4441 "%s: MAX TM Level Scan not allowed", __func__);
4442 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4443 return -EBUSY;
4444 }
4445 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4446
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004447 /* Check if scan is allowed at this point of time.
4448 */
4449 if (!hdd_isScanAllowed(pHddCtx))
4450 {
4451 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
4452 return -EBUSY;
4453 }
4454
Jeff Johnson295189b2012-06-20 16:38:30 -07004455 vos_mem_zero( &scanRequest, sizeof(scanRequest));
4456
4457 if (NULL != request)
4458 {
4459 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
4460 (int)request->n_ssids);
4461
4462 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
4463 * Becasue of this, driver is assuming that this is not wildcard scan and so
4464 * is not aging out the scan results.
4465 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07004466 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07004467 {
4468 request->n_ssids = 0;
4469 }
4470
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004471 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07004472 {
4473 tCsrSSIDInfo *SsidInfo;
4474 int j;
4475 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
4476 /* Allocate num_ssid tCsrSSIDInfo structure */
4477 SsidInfo = scanRequest.SSIDs.SSIDList =
4478 ( tCsrSSIDInfo *)vos_mem_malloc(
4479 request->n_ssids*sizeof(tCsrSSIDInfo));
4480
4481 if(NULL == scanRequest.SSIDs.SSIDList)
4482 {
4483 hddLog(VOS_TRACE_LEVEL_ERROR,
4484 "memory alloc failed SSIDInfo buffer");
4485 return -ENOMEM;
4486 }
4487
4488 /* copy all the ssid's and their length */
4489 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
4490 {
4491 /* get the ssid length */
4492 SsidInfo->SSID.length = request->ssids[j].ssid_len;
4493 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
4494 SsidInfo->SSID.length);
4495 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
4496 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
4497 j, SsidInfo->SSID.ssId);
4498 }
4499 /* set the scan type to active */
4500 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4501 }
4502 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4503 {
4504 /* set the scan type to active */
4505 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4506 }
4507 else
4508 {
4509 /*Set the scan type to default type, in this case it is ACTIVE*/
4510 scanRequest.scanType = pScanInfo->scan_mode;
4511 }
4512 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
4513 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4514 }
4515 else
4516 {
4517 /* set the scan type to active */
4518 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4519 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4520
4521 /* set min and max channel time to zero */
4522 scanRequest.minChnTime = 0;
4523 scanRequest.maxChnTime = 0;
4524 }
4525
4526 /* set BSSType to default type */
4527 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4528
4529 /*TODO: scan the requested channels only*/
4530
4531 /*Right now scanning all the channels */
4532 if( request )
4533 {
4534 if( request->n_channels )
4535 {
4536 channelList = vos_mem_malloc( request->n_channels );
4537 if( NULL == channelList )
4538 {
4539 status = -ENOMEM;
4540 goto free_mem;
4541 }
4542
4543 for( i = 0 ; i < request->n_channels ; i++ )
4544 channelList[i] = request->channels[i]->hw_value;
4545 }
4546
4547 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4548 scanRequest.ChannelInfo.ChannelList = channelList;
4549
4550 /* set requestType to full scan */
4551 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004552
4553 /* Flush the scan results(only p2p beacons) for STA scan and P2P
4554 * search (Flush on both full scan and social scan but not on single
4555 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
4556 */
4557
4558 /* Supplicant does single channel scan after 8-way handshake
4559 * and in that case driver shoudnt flush scan results. If
4560 * driver flushes the scan results here and unfortunately if
4561 * the AP doesnt respond to our probe req then association
4562 * fails which is not desired
4563 */
4564
4565 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4566 {
4567 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4568 pAdapter->sessionId );
4569 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004570
4571 if( request->ie_len )
4572 {
4573 /* save this for future association (join requires this) */
4574 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4575 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4576 pScanInfo->scanAddIE.length = request->ie_len;
4577
4578 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004579 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4580 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004581 )
4582 {
4583 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4584 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4585 }
4586
4587 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4588 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4589
Jeff Johnson295189b2012-06-20 16:38:30 -07004590 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4591 request->ie_len);
4592 if (pP2pIe != NULL)
4593 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004594#ifdef WLAN_FEATURE_P2P_DEBUG
4595 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4596 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4597 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4598 {
4599 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4600 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4601 "Go nego completed to Connection is started");
4602 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4603 "for 8way Handshake");
4604 }
4605 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4606 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4607 {
4608 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4609 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4610 "Disconnected state to Connection is started");
4611 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4612 "for 4way Handshake");
4613 }
4614#endif
4615
Jeff Johnsone7245742012-09-05 17:12:55 -07004616 /* no_cck will be set during p2p find to disable 11b rates */
4617 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004618 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004619 hddLog(VOS_TRACE_LEVEL_INFO,
4620 "%s: This is a P2P Search", __func__);
4621 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004622
Jeff Johnsone7245742012-09-05 17:12:55 -07004623 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4624 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004625 /* set requestType to P2P Discovery */
4626 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004627 }
4628
4629 /*
4630 Skip Dfs Channel in case of P2P Search
4631 if it is set in ini file
4632 */
4633 if(cfg_param->skipDfsChnlInP2pSearch)
4634 {
4635 scanRequest.skipDfsChnlInP2pSearch = 1;
4636 }
4637 else
4638 {
4639 scanRequest.skipDfsChnlInP2pSearch = 0;
4640 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004641
Jeff Johnson295189b2012-06-20 16:38:30 -07004642 }
4643 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004644 }
4645 }
4646
4647 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4648
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004649 /* acquire the wakelock to avoid the apps suspend during the scan. To
4650 * address the following issues.
4651 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4652 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4653 * for long time, this result in apps running at full power for long time.
4654 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4655 * be stuck in full power because of resume BMPS
4656 */
4657 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004658
4659 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004660 pAdapter->sessionId, &scanRequest, &scanId,
4661 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004662
Jeff Johnson295189b2012-06-20 16:38:30 -07004663 if (eHAL_STATUS_SUCCESS != status)
4664 {
4665 hddLog(VOS_TRACE_LEVEL_ERROR,
4666 "%s: sme_ScanRequest returned error %d", __func__, status);
4667 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004668 if(eHAL_STATUS_RESOURCES == status)
4669 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004670 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 -07004671 status = -EBUSY;
4672 } else {
4673 status = -EIO;
4674 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004675 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004676 goto free_mem;
4677 }
4678
4679 pScanInfo->mScanPending = TRUE;
4680 pAdapter->request = request;
4681 pScanInfo->scanId = scanId;
4682
4683 complete(&pScanInfo->scan_req_completion_event);
4684
4685free_mem:
4686 if( scanRequest.SSIDs.SSIDList )
4687 {
4688 vos_mem_free(scanRequest.SSIDs.SSIDList);
4689 }
4690
4691 if( channelList )
4692 vos_mem_free( channelList );
4693
4694 EXIT();
4695
4696 return status;
4697}
4698
4699/*
4700 * FUNCTION: wlan_hdd_cfg80211_connect_start
4701 * This function is used to start the association process
4702 */
4703int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004704 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004705{
4706 int status = 0;
4707 hdd_wext_state_t *pWextState;
4708 v_U32_t roamId;
4709 tCsrRoamProfile *pRoamProfile;
4710 eMib_dot11DesiredBssType connectedBssType;
4711 eCsrAuthType RSNAuthType;
4712
4713 ENTER();
4714
4715 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4716
4717 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4718 {
4719 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4720 return -EINVAL;
4721 }
4722
4723 pRoamProfile = &pWextState->roamProfile;
4724
4725 if (pRoamProfile)
4726 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004727 int ret = 0;
4728 hdd_station_ctx_t *pHddStaCtx;
4729 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4730 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4731
4732 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4733 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4734 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004735 {
4736 /* Issue disconnect to CSR */
4737 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4738 if( eHAL_STATUS_SUCCESS ==
4739 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4740 pAdapter->sessionId,
4741 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4742 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004743 ret = wait_for_completion_interruptible_timeout(
4744 &pAdapter->disconnect_comp_var,
4745 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4746 if (0 == ret)
4747 {
4748 VOS_ASSERT(0);
4749 }
4750 }
4751 }
4752 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4753 {
4754 ret = wait_for_completion_interruptible_timeout(
4755 &pAdapter->disconnect_comp_var,
4756 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4757 if (0 == ret)
4758 {
4759 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004760 }
4761 }
4762
4763 if (HDD_WMM_USER_MODE_NO_QOS ==
4764 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4765 {
4766 /*QoS not enabled in cfg file*/
4767 pRoamProfile->uapsd_mask = 0;
4768 }
4769 else
4770 {
4771 /*QoS enabled, update uapsd mask from cfg file*/
4772 pRoamProfile->uapsd_mask =
4773 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4774 }
4775
4776 pRoamProfile->SSIDs.numOfSSIDs = 1;
4777 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4778 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
4779 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
4780 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4781 ssid, ssid_len);
4782
4783 if (bssid)
4784 {
4785 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4786 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4787 WNI_CFG_BSSID_LEN);
4788 /* Save BSSID in seperate variable as well, as RoamProfile
4789 BSSID is getting zeroed out in the association process. And in
4790 case of join failure we should send valid BSSID to supplicant
4791 */
4792 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4793 WNI_CFG_BSSID_LEN);
4794 }
4795
4796 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4797 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4798 {
4799 /*set gen ie*/
4800 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4801 /*set auth*/
4802 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4803 }
4804 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4805 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4806 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4807 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4808 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4809 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4810 )
4811 {
4812 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4813 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4814 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4815 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4816 eCSR_AUTH_TYPE_AUTOSWITCH;
4817 pWextState->roamProfile.AuthType.authType[0] =
4818 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4819 }
4820#ifdef FEATURE_WLAN_WAPI
4821 if (pAdapter->wapi_info.nWapiMode)
4822 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004823 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004824 switch (pAdapter->wapi_info.wapiAuthMode)
4825 {
4826 case WAPI_AUTH_MODE_PSK:
4827 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004828 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004829 pAdapter->wapi_info.wapiAuthMode);
4830 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4831 break;
4832 }
4833 case WAPI_AUTH_MODE_CERT:
4834 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004835 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004836 pAdapter->wapi_info.wapiAuthMode);
4837 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4838 break;
4839 }
4840 } // End of switch
4841 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4842 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4843 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004844 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004845 pRoamProfile->AuthType.numEntries = 1;
4846 pRoamProfile->EncryptionType.numEntries = 1;
4847 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4848 pRoamProfile->mcEncryptionType.numEntries = 1;
4849 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4850 }
4851 }
4852#endif /* FEATURE_WLAN_WAPI */
4853 pRoamProfile->csrPersona = pAdapter->device_mode;
4854
Jeff Johnson32d95a32012-09-10 13:15:23 -07004855 if( operatingChannel )
4856 {
4857 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4858 pRoamProfile->ChannelInfo.numOfChannels = 1;
4859 }
Chet Lanctot186b5732013-03-18 10:26:30 -07004860 else
4861 {
4862 pRoamProfile->ChannelInfo.ChannelList = NULL;
4863 pRoamProfile->ChannelInfo.numOfChannels = 0;
4864 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004865
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004866 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
4867 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
4868 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
4869 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004870 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
4871 */
4872 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4873 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
4874 eConnectionState_Connecting);
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004875
Jeff Johnson295189b2012-06-20 16:38:30 -07004876 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4877 pAdapter->sessionId, pRoamProfile, &roamId);
4878
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004879 if( (eHAL_STATUS_SUCCESS != status) &&
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304880 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
4881
4882 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004883 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
4884 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
4885 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304886 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004887 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304888 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004889
4890 pRoamProfile->ChannelInfo.ChannelList = NULL;
4891 pRoamProfile->ChannelInfo.numOfChannels = 0;
4892
Jeff Johnson295189b2012-06-20 16:38:30 -07004893 }
4894 else
4895 {
4896 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4897 return -EINVAL;
4898 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004899 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004900 return status;
4901}
4902
4903/*
4904 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4905 * This function is used to set the authentication type (OPEN/SHARED).
4906 *
4907 */
4908static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4909 enum nl80211_auth_type auth_type)
4910{
4911 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4912 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4913
4914 ENTER();
4915
4916 /*set authentication type*/
4917 switch (auth_type)
4918 {
4919 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4920 case NL80211_AUTHTYPE_AUTOMATIC:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07004921#ifdef WLAN_FEATURE_VOWIFI_11R
4922 case NL80211_AUTHTYPE_FT:
4923#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07004924 hddLog(VOS_TRACE_LEVEL_INFO,
4925 "%s: set authentication type to OPEN", __func__);
4926 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4927 break;
4928
4929 case NL80211_AUTHTYPE_SHARED_KEY:
4930 hddLog(VOS_TRACE_LEVEL_INFO,
4931 "%s: set authentication type to SHARED", __func__);
4932 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4933 break;
4934#ifdef FEATURE_WLAN_CCX
4935 case NL80211_AUTHTYPE_NETWORK_EAP:
4936 hddLog(VOS_TRACE_LEVEL_INFO,
4937 "%s: set authentication type to CCKM WPA", __func__);
4938 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4939 break;
4940#endif
4941
4942
4943 default:
4944 hddLog(VOS_TRACE_LEVEL_ERROR,
4945 "%s: Unsupported authentication type %d", __func__,
4946 auth_type);
4947 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4948 return -EINVAL;
4949 }
4950
4951 pWextState->roamProfile.AuthType.authType[0] =
4952 pHddStaCtx->conn_info.authType;
4953 return 0;
4954}
4955
4956/*
4957 * FUNCTION: wlan_hdd_set_akm_suite
4958 * This function is used to set the key mgmt type(PSK/8021x).
4959 *
4960 */
4961static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
4962 u32 key_mgmt
4963 )
4964{
4965 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4966 ENTER();
4967
4968 /*set key mgmt type*/
4969 switch(key_mgmt)
4970 {
4971 case WLAN_AKM_SUITE_PSK:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05304972#ifdef WLAN_FEATURE_VOWIFI_11R
4973 case WLAN_AKM_SUITE_FT_PSK:
4974#endif
4975 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
Jeff Johnson295189b2012-06-20 16:38:30 -07004976 __func__);
4977 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
4978 break;
4979
4980 case WLAN_AKM_SUITE_8021X:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05304981#ifdef WLAN_FEATURE_VOWIFI_11R
4982 case WLAN_AKM_SUITE_FT_8021X:
4983#endif
4984 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
Jeff Johnson295189b2012-06-20 16:38:30 -07004985 __func__);
4986 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
4987 break;
4988#ifdef FEATURE_WLAN_CCX
4989#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
4990#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
4991 case WLAN_AKM_SUITE_CCKM:
4992 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
4993 __func__);
4994 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
4995 break;
4996#endif
4997
4998 default:
4999 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
5000 __func__, key_mgmt);
5001 return -EINVAL;
5002
5003 }
5004 return 0;
5005}
5006
5007/*
5008 * FUNCTION: wlan_hdd_cfg80211_set_cipher
5009 * This function is used to set the encryption type
5010 * (NONE/WEP40/WEP104/TKIP/CCMP).
5011 */
5012static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
5013 u32 cipher,
5014 bool ucast
5015 )
5016{
5017 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5018 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5019 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5020
5021 ENTER();
5022
5023 if (!cipher)
5024 {
5025 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
5026 __func__, cipher);
5027 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5028 }
5029 else
5030 {
5031
5032 /*set encryption method*/
5033 switch (cipher)
5034 {
5035 case IW_AUTH_CIPHER_NONE:
5036 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5037 break;
5038
5039 case WLAN_CIPHER_SUITE_WEP40:
5040 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
5041 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
5042 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
5043 else
5044 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5045 break;
5046
5047 case WLAN_CIPHER_SUITE_WEP104:
5048 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
5049 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
5050 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
5051 else
5052 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
5053 break;
5054
5055 case WLAN_CIPHER_SUITE_TKIP:
5056 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5057 break;
5058
5059 case WLAN_CIPHER_SUITE_CCMP:
5060 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5061 break;
5062#ifdef FEATURE_WLAN_WAPI
5063 case WLAN_CIPHER_SUITE_SMS4:
5064 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
5065 break;
5066#endif
5067
5068#ifdef FEATURE_WLAN_CCX
5069 case WLAN_CIPHER_SUITE_KRK:
5070 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
5071 break;
5072#endif
5073 default:
5074 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
5075 __func__, cipher);
5076 return -EOPNOTSUPP;
5077 }
5078 }
5079
5080 if (ucast)
5081 {
5082 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
5083 __func__, encryptionType);
5084 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5085 pWextState->roamProfile.EncryptionType.numEntries = 1;
5086 pWextState->roamProfile.EncryptionType.encryptionType[0] =
5087 encryptionType;
5088 }
5089 else
5090 {
5091 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
5092 __func__, encryptionType);
5093 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
5094 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
5095 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
5096 }
5097
5098 return 0;
5099}
5100
5101
5102/*
5103 * FUNCTION: wlan_hdd_cfg80211_set_ie
5104 * This function is used to parse WPA/RSN IE's.
5105 */
5106int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
5107 u8 *ie,
5108 size_t ie_len
5109 )
5110{
5111 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5112 u8 *genie = ie;
5113 v_U16_t remLen = ie_len;
5114#ifdef FEATURE_WLAN_WAPI
5115 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
5116 u16 *tmp;
5117 v_U16_t akmsuiteCount;
5118 int *akmlist;
5119#endif
5120 ENTER();
5121
5122 /* clear previous assocAddIE */
5123 pWextState->assocAddIE.length = 0;
5124 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
5125
5126 while (remLen >= 2)
5127 {
5128 v_U16_t eLen = 0;
5129 v_U8_t elementId;
5130 elementId = *genie++;
5131 eLen = *genie++;
5132 remLen -= 2;
5133
5134 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
5135 __func__, elementId, eLen);
5136
5137 switch ( elementId )
5138 {
5139 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005140 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 -07005141 {
5142 hddLog(VOS_TRACE_LEVEL_ERROR,
5143 "%s: Invalid WPA IE", __func__);
5144 return -EINVAL;
5145 }
5146 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
5147 {
5148 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5149 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
5150 __func__, eLen + 2);
5151
5152 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5153 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005154 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
5155 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005156 VOS_ASSERT(0);
5157 return -ENOMEM;
5158 }
5159 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5160 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5161 pWextState->assocAddIE.length += eLen + 2;
5162
5163 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
5164 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5165 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5166 }
5167 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
5168 {
5169 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
5170 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5171 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
5172 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
5173 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
5174 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005175 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
5176 P2P_OUI_TYPE_SIZE))
5177 /*Consider P2P IE, only for P2P Client */
5178 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5179 {
5180 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5181 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
5182 __func__, eLen + 2);
5183
5184 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5185 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005186 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5187 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005188 VOS_ASSERT(0);
5189 return -ENOMEM;
5190 }
5191 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5192 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5193 pWextState->assocAddIE.length += eLen + 2;
5194
5195 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5196 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5197 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005198#ifdef WLAN_FEATURE_WFD
5199 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
5200 WFD_OUI_TYPE_SIZE))
5201 /*Consider WFD IE, only for P2P Client */
5202 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5203 {
5204 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5205 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
5206 __func__, eLen + 2);
5207
5208 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5209 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005210 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5211 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005212 VOS_ASSERT(0);
5213 return -ENOMEM;
5214 }
5215 // WFD IE is saved to Additional IE ; it should be accumulated to handle
5216 // WPS IE + P2P IE + WFD IE
5217 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5218 pWextState->assocAddIE.length += eLen + 2;
5219
5220 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5221 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5222 }
5223#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005224 /* Appending HS 2.0 Indication Element in Assiciation Request */
5225 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005226 HS20_OUI_TYPE_SIZE)) )
5227 {
5228 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5229 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
5230 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005231
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005232 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5233 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005234 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5235 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005236 VOS_ASSERT(0);
5237 return -ENOMEM;
5238 }
5239 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5240 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005241
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005242 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5243 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5244 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005245
Jeff Johnson295189b2012-06-20 16:38:30 -07005246 break;
5247 case DOT11F_EID_RSN:
5248 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
5249 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5250 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
5251 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
5252 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
5253 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005254 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
5255 case DOT11F_EID_EXTCAP:
5256 {
5257 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5258 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
5259 __func__, eLen + 2);
5260
5261 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5262 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005263 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5264 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005265 VOS_ASSERT(0);
5266 return -ENOMEM;
5267 }
5268 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5269 pWextState->assocAddIE.length += eLen + 2;
5270
5271 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5272 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5273 break;
5274 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005275#ifdef FEATURE_WLAN_WAPI
5276 case WLAN_EID_WAPI:
5277 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
5278 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
5279 pAdapter->wapi_info.nWapiMode);
5280 tmp = (u16 *)ie;
5281 tmp = tmp + 2; // Skip element Id and Len, Version
5282 akmsuiteCount = WPA_GET_LE16(tmp);
5283 tmp = tmp + 1;
5284 akmlist = (int *)(tmp);
5285 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
5286 {
5287 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
5288 }
5289 else
5290 {
5291 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
5292 VOS_ASSERT(0);
5293 return -EINVAL;
5294 }
5295
5296 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
5297 {
5298 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005299 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005300 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
5301 }
5302 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
5303 {
5304 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005305 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005306 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
5307 }
5308 break;
5309#endif
5310 default:
5311 hddLog (VOS_TRACE_LEVEL_ERROR,
5312 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005313 /* when Unknown IE is received we should break and continue
5314 * to the next IE in the buffer instead we were returning
5315 * so changing this to break */
5316 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005317 }
5318 genie += eLen;
5319 remLen -= eLen;
5320 }
5321 EXIT();
5322 return 0;
5323}
5324
5325/*
5326 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5327 * This function is used to initialize the security
5328 * parameters during connect operation.
5329 */
5330int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
5331 struct cfg80211_connect_params *req
5332 )
5333{
5334 int status = 0;
5335 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5336 ENTER();
5337
5338 /*set wpa version*/
5339 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5340
5341 if (req->crypto.wpa_versions)
5342 {
5343 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
5344 && ( (req->ie_len)
5345 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
5346 // Make sure that it is including a WPA IE.
5347 /* Currently NL is putting WPA version 1 even for open,
5348 * since p2p ie is also put in same buffer.
5349 * */
5350 {
5351 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5352 }
5353 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
5354 {
5355 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5356 }
5357 }
5358
5359 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
5360 pWextState->wpaVersion);
5361
5362 /*set authentication type*/
5363 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
5364
5365 if (0 > status)
5366 {
5367 hddLog(VOS_TRACE_LEVEL_ERROR,
5368 "%s: failed to set authentication type ", __func__);
5369 return status;
5370 }
5371
5372 /*set key mgmt type*/
5373 if (req->crypto.n_akm_suites)
5374 {
5375 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
5376 if (0 > status)
5377 {
5378 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
5379 __func__);
5380 return status;
5381 }
5382 }
5383
5384 /*set pairwise cipher type*/
5385 if (req->crypto.n_ciphers_pairwise)
5386 {
5387 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
5388 req->crypto.ciphers_pairwise[0], true);
5389 if (0 > status)
5390 {
5391 hddLog(VOS_TRACE_LEVEL_ERROR,
5392 "%s: failed to set unicast cipher type", __func__);
5393 return status;
5394 }
5395 }
5396 else
5397 {
5398 /*Reset previous cipher suite to none*/
5399 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
5400 if (0 > status)
5401 {
5402 hddLog(VOS_TRACE_LEVEL_ERROR,
5403 "%s: failed to set unicast cipher type", __func__);
5404 return status;
5405 }
5406 }
5407
5408 /*set group cipher type*/
5409 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
5410 false);
5411
5412 if (0 > status)
5413 {
5414 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
5415 __func__);
5416 return status;
5417 }
5418
Chet Lanctot186b5732013-03-18 10:26:30 -07005419#ifdef WLAN_FEATURE_11W
5420 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
5421#endif
5422
Jeff Johnson295189b2012-06-20 16:38:30 -07005423 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
5424 if (req->ie_len)
5425 {
5426 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
5427 if ( 0 > status)
5428 {
5429 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
5430 __func__);
5431 return status;
5432 }
5433 }
5434
5435 /*incase of WEP set default key information*/
5436 if (req->key && req->key_len)
5437 {
5438 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
5439 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
5440 )
5441 {
5442 if ( IW_AUTH_KEY_MGMT_802_1X
5443 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
5444 {
5445 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
5446 __func__);
5447 return -EOPNOTSUPP;
5448 }
5449 else
5450 {
5451 u8 key_len = req->key_len;
5452 u8 key_idx = req->key_idx;
5453
5454 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
5455 && (CSR_MAX_NUM_KEY > key_idx)
5456 )
5457 {
5458 hddLog(VOS_TRACE_LEVEL_INFO,
5459 "%s: setting default wep key, key_idx = %hu key_len %hu",
5460 __func__, key_idx, key_len);
5461 vos_mem_copy(
5462 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
5463 req->key, key_len);
5464 pWextState->roamProfile.Keys.KeyLength[key_idx] =
5465 (u8)key_len;
5466 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
5467 }
5468 }
5469 }
5470 }
5471
5472 return status;
5473}
5474
5475/*
5476 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5477 * This function is used to initialize the security
5478 * parameters during connect operation.
5479 */
5480static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
5481 struct net_device *ndev,
5482 struct cfg80211_connect_params *req
5483 )
5484{
5485 int status = 0;
5486 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
5487 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
5488 hdd_context_t *pHddCtx = NULL;
5489
5490 ENTER();
5491
5492 hddLog(VOS_TRACE_LEVEL_INFO,
5493 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5494
5495 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5496 {
5497 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5498 "%s:LOGP in Progress. Ignore!!!", __func__);
5499 return -EAGAIN;
5500 }
5501
5502#ifdef WLAN_BTAMP_FEATURE
5503 //Infra connect not supported when AMP traffic is on.
5504 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
5505 {
5506 hddLog(VOS_TRACE_LEVEL_ERROR,
5507 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005508 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07005509 }
5510#endif
5511 /*initialise security parameters*/
5512 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
5513
5514 if ( 0 > status)
5515 {
5516 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
5517 __func__);
5518 return status;
5519 }
5520
5521 //If Device Mode is Station Concurrent Sessions Exit BMps
Jeff Johnsona8a1a482012-12-12 16:49:33 -08005522 //P2P Mode will be taken care in Open/close adapter
Jeff Johnson295189b2012-06-20 16:38:30 -07005523 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
5524 (vos_concurrent_sessions_running()))
5525 {
5526 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5527
5528 if (NULL != pVosContext)
5529 {
5530 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5531 if(NULL != pHddCtx)
5532 {
5533 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
5534 }
5535 }
5536 }
5537
Mohit Khanna765234a2012-09-11 15:08:35 -07005538 if ( req->channel )
5539 {
5540 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5541 req->ssid_len, req->bssid,
5542 req->channel->hw_value);
5543 }
5544 else
5545 {
5546 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5547 req->ssid_len, req->bssid,
5548 0);
5549 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005550
5551 if (0 > status)
5552 {
5553 //ReEnable BMPS if disabled
5554 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5555 (NULL != pHddCtx))
5556 {
5557 //ReEnable Bmps and Imps back
5558 hdd_enable_bmps_imps(pHddCtx);
5559 }
5560
5561 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5562 return status;
5563 }
5564 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
5565 EXIT();
5566 return status;
5567}
5568
5569
5570/*
5571 * FUNCTION: wlan_hdd_cfg80211_disconnect
5572 * This function is used to issue a disconnect request to SME
5573 */
5574static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
5575 struct net_device *dev,
5576 u16 reason
5577 )
5578{
5579 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5580 tCsrRoamProfile *pRoamProfile =
5581 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
5582 int status = 0;
5583 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005584#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005585 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005586 tANI_U8 staIdx;
5587#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005588
5589 ENTER();
5590
5591 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
5592 __func__,pAdapter->device_mode);
5593
5594 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5595 __func__, reason);
5596
5597 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
5598 {
5599 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5600 "%s:LOGP in Progress. Ignore!!!",__func__);
5601 return -EAGAIN;
5602 }
5603 if (NULL != pRoamProfile)
5604 {
5605 /*issue disconnect request to SME, if station is in connected state*/
5606 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
5607 {
5608 eCsrRoamDisconnectReason reasonCode =
5609 eCSR_DISCONNECT_REASON_UNSPECIFIED;
5610 switch(reason)
5611 {
5612 case WLAN_REASON_MIC_FAILURE:
5613 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
5614 break;
5615
5616 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
5617 case WLAN_REASON_DISASSOC_AP_BUSY:
5618 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
5619 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
5620 break;
5621
5622 case WLAN_REASON_PREV_AUTH_NOT_VALID:
5623 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
5624 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
5625 break;
5626
5627 case WLAN_REASON_DEAUTH_LEAVING:
5628 default:
5629 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
5630 break;
5631 }
5632 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5633 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
5634 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5635
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005636#ifdef FEATURE_WLAN_TDLS
5637 /* First clean up the tdls peers if any */
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005638 for (staIdx = 0 ; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005639 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005640 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId == pAdapter->sessionId) &&
5641 (pHddCtx->tdlsConnInfo[staIdx].staId))
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005642 {
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005643 uint8 *mac;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005644 mac = pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005645 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07005646 "%s: call sme_DeleteTdlsPeerSta staId %d sessionId %d " MAC_ADDRESS_STR,
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005647 __func__, pHddCtx->tdlsConnInfo[staIdx].staId, pAdapter->sessionId,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07005648 MAC_ADDR_ARRAY(mac));
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005649 sme_DeleteTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005650 pAdapter->sessionId,
5651 mac);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005652 }
5653 }
5654#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005655 /*issue disconnect*/
5656 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5657 pAdapter->sessionId, reasonCode);
5658
5659 if ( 0 != status)
5660 {
5661 hddLog(VOS_TRACE_LEVEL_ERROR,
5662 "%s csrRoamDisconnect failure, returned %d \n",
5663 __func__, (int)status );
5664 return -EINVAL;
5665 }
5666
5667 wait_for_completion_interruptible_timeout(
5668 &pAdapter->disconnect_comp_var,
5669 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5670
5671
5672 /*stop tx queues*/
5673 netif_tx_disable(dev);
5674 netif_carrier_off(dev);
5675 }
5676 }
5677 else
5678 {
5679 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
5680 }
5681
5682 return status;
5683}
5684
5685/*
5686 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
5687 * This function is used to initialize the security
5688 * settings in IBSS mode.
5689 */
5690static int wlan_hdd_cfg80211_set_privacy_ibss(
5691 hdd_adapter_t *pAdapter,
5692 struct cfg80211_ibss_params *params
5693 )
5694{
5695 int status = 0;
5696 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5697 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5698 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5699
5700 ENTER();
5701
5702 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5703
5704 if (params->ie_len && ( NULL != params->ie) )
5705 {
5706 if (WLAN_EID_RSN == params->ie[0])
5707 {
5708 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5709 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5710 }
5711 else
5712 {
5713 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5714 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5715 }
5716 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
5717
5718 if (0 > status)
5719 {
5720 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
5721 __func__);
5722 return status;
5723 }
5724 }
5725
5726 pWextState->roamProfile.AuthType.authType[0] =
5727 pHddStaCtx->conn_info.authType =
5728 eCSR_AUTH_TYPE_OPEN_SYSTEM;
5729
5730 if (params->privacy)
5731 {
5732 /* Security enabled IBSS, At this time there is no information available
5733 * about the security paramters, so initialise the encryption type to
5734 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
5735 * The correct security parameters will be updated later in
5736 * wlan_hdd_cfg80211_add_key */
5737 /* Hal expects encryption type to be set inorder
5738 *enable privacy bit in beacons */
5739
5740 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5741 }
5742
5743 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5744 pWextState->roamProfile.EncryptionType.numEntries = 1;
5745 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
5746
5747 return status;
5748}
5749
5750/*
5751 * FUNCTION: wlan_hdd_cfg80211_join_ibss
5752 * This function is used to create/join an IBSS
5753 */
5754static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
5755 struct net_device *dev,
5756 struct cfg80211_ibss_params *params
5757 )
5758{
5759 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5760 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5761 tCsrRoamProfile *pRoamProfile;
5762 int status;
5763 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5764
5765 ENTER();
5766
5767 hddLog(VOS_TRACE_LEVEL_INFO,
5768 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5769
5770 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5771 {
5772 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5773 "%s:LOGP in Progress. Ignore!!!", __func__);
5774 return -EAGAIN;
5775 }
5776
5777 if (NULL == pWextState)
5778 {
5779 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5780 __func__);
5781 return -EIO;
5782 }
5783
5784 pRoamProfile = &pWextState->roamProfile;
5785
5786 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
5787 {
5788 hddLog (VOS_TRACE_LEVEL_ERROR,
5789 "%s Interface type is not set to IBSS \n", __func__);
5790 return -EINVAL;
5791 }
5792
5793 /* Set Channel */
5794 if (NULL != params->channel)
5795 {
5796 u8 channelNum;
5797 if (IEEE80211_BAND_5GHZ == params->channel->band)
5798 {
5799 hddLog(VOS_TRACE_LEVEL_ERROR,
5800 "%s: IBSS join is called with unsupported band %d",
5801 __func__, params->channel->band);
5802 return -EOPNOTSUPP;
5803 }
5804
5805 /* Get channel number */
5806 channelNum =
5807 ieee80211_frequency_to_channel(params->channel->center_freq);
5808
5809 /*TODO: use macro*/
5810 if (14 >= channelNum)
5811 {
5812 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5813 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5814 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5815 int indx;
5816
5817 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5818 validChan, &numChans))
5819 {
5820 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
5821 __func__);
5822 return -EOPNOTSUPP;
5823 }
5824
5825 for (indx = 0; indx < numChans; indx++)
5826 {
5827 if (channelNum == validChan[indx])
5828 {
5829 break;
5830 }
5831 }
5832 if (indx >= numChans)
5833 {
5834 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
5835 __func__, channelNum);
5836 return -EINVAL;
5837 }
5838 /* Set the Operational Channel */
5839 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
5840 channelNum);
5841 pRoamProfile->ChannelInfo.numOfChannels = 1;
5842 pHddStaCtx->conn_info.operationChannel = channelNum;
5843 pRoamProfile->ChannelInfo.ChannelList =
5844 &pHddStaCtx->conn_info.operationChannel;
5845 }
5846 else
5847 {
5848 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5849 __func__, channelNum);
5850 return -EINVAL;
5851 }
5852 }
5853
5854 /* Initialize security parameters */
5855 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5856 if (status < 0)
5857 {
5858 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5859 __func__);
5860 return status;
5861 }
5862
5863 /* Issue connect start */
5864 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005865 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005866
5867 if (0 > status)
5868 {
5869 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5870 return status;
5871 }
5872
5873 return 0;
5874}
5875
5876/*
5877 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5878 * This function is used to leave an IBSS
5879 */
5880static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5881 struct net_device *dev
5882 )
5883{
5884 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5885 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5886 tCsrRoamProfile *pRoamProfile;
5887
5888 ENTER();
5889
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005890 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5891 {
5892 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5893 "%s:LOGP in Progress. Ignore!!!", __func__);
5894 return -EAGAIN;
5895 }
5896
Jeff Johnson295189b2012-06-20 16:38:30 -07005897 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5898 if (NULL == pWextState)
5899 {
5900 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5901 __func__);
5902 return -EIO;
5903 }
5904
5905 pRoamProfile = &pWextState->roamProfile;
5906
5907 /* Issue disconnect only if interface type is set to IBSS */
5908 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5909 {
5910 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5911 __func__);
5912 return -EINVAL;
5913 }
5914
5915 /* Issue Disconnect request */
5916 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5917 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5918 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5919
5920 return 0;
5921}
5922
5923/*
5924 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5925 * This function is used to set the phy parameters
5926 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5927 */
5928static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5929 u32 changed)
5930{
5931 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5932 tHalHandle hHal = pHddCtx->hHal;
5933
5934 ENTER();
5935
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005936 if ( pHddCtx->isLogpInProgress )
5937 {
5938 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5939 "%s:LOGP in Progress. Ignore!!!", __func__);
5940 return -EAGAIN;
5941 }
5942
Jeff Johnson295189b2012-06-20 16:38:30 -07005943 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
5944 {
5945 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
5946 WNI_CFG_RTS_THRESHOLD_STAMAX :
5947 wiphy->rts_threshold;
5948
5949 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
5950 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
5951 {
5952 hddLog(VOS_TRACE_LEVEL_ERROR,
5953 "%s: Invalid RTS Threshold value %hu",
5954 __func__, rts_threshold);
5955 return -EINVAL;
5956 }
5957
5958 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
5959 rts_threshold, ccmCfgSetCallback,
5960 eANI_BOOLEAN_TRUE))
5961 {
5962 hddLog(VOS_TRACE_LEVEL_ERROR,
5963 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
5964 __func__, rts_threshold);
5965 return -EIO;
5966 }
5967
5968 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
5969 rts_threshold);
5970 }
5971
5972 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
5973 {
5974 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
5975 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
5976 wiphy->frag_threshold;
5977
5978 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
5979 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
5980 {
5981 hddLog(VOS_TRACE_LEVEL_ERROR,
5982 "%s: Invalid frag_threshold value %hu", __func__,
5983 frag_threshold);
5984 return -EINVAL;
5985 }
5986
5987 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
5988 frag_threshold, ccmCfgSetCallback,
5989 eANI_BOOLEAN_TRUE))
5990 {
5991 hddLog(VOS_TRACE_LEVEL_ERROR,
5992 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
5993 __func__, frag_threshold);
5994 return -EIO;
5995 }
5996
5997 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
5998 frag_threshold);
5999 }
6000
6001 if ((changed & WIPHY_PARAM_RETRY_SHORT)
6002 || (changed & WIPHY_PARAM_RETRY_LONG))
6003 {
6004 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
6005 wiphy->retry_short :
6006 wiphy->retry_long;
6007
6008 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
6009 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
6010 {
6011 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
6012 __func__, retry_value);
6013 return -EINVAL;
6014 }
6015
6016 if (changed & WIPHY_PARAM_RETRY_SHORT)
6017 {
6018 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
6019 retry_value, ccmCfgSetCallback,
6020 eANI_BOOLEAN_TRUE))
6021 {
6022 hddLog(VOS_TRACE_LEVEL_ERROR,
6023 "%s: ccmCfgSetInt failed for long retry count %hu",
6024 __func__, retry_value);
6025 return -EIO;
6026 }
6027 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
6028 __func__, retry_value);
6029 }
6030 else if (changed & WIPHY_PARAM_RETRY_SHORT)
6031 {
6032 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
6033 retry_value, ccmCfgSetCallback,
6034 eANI_BOOLEAN_TRUE))
6035 {
6036 hddLog(VOS_TRACE_LEVEL_ERROR,
6037 "%s: ccmCfgSetInt failed for short retry count %hu",
6038 __func__, retry_value);
6039 return -EIO;
6040 }
6041 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
6042 __func__, retry_value);
6043 }
6044 }
6045
6046 return 0;
6047}
6048
6049/*
6050 * FUNCTION: wlan_hdd_cfg80211_set_txpower
6051 * This function is used to set the txpower
6052 */
6053static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
6054#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
6055 enum tx_power_setting type,
6056#else
6057 enum nl80211_tx_power_setting type,
6058#endif
6059 int dbm)
6060{
6061 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6062 tHalHandle hHal = pHddCtx->hHal;
6063 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
6064 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
6065
6066 ENTER();
6067
6068 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
6069 dbm, ccmCfgSetCallback,
6070 eANI_BOOLEAN_TRUE))
6071 {
6072 hddLog(VOS_TRACE_LEVEL_ERROR,
6073 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
6074 return -EIO;
6075 }
6076
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006077 if ( pHddCtx->isLogpInProgress )
6078 {
6079 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6080 "%s:LOGP in Progress. Ignore!!!", __func__);
6081 return -EAGAIN;
6082 }
6083
Jeff Johnson295189b2012-06-20 16:38:30 -07006084 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
6085 dbm);
6086
6087 switch(type)
6088 {
6089 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
6090 /* Fall through */
6091 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
6092 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
6093 {
6094 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
6095 __func__);
6096 return -EIO;
6097 }
6098 break;
6099 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
6100 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
6101 __func__);
6102 return -EOPNOTSUPP;
6103 break;
6104 default:
6105 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
6106 __func__, type);
6107 return -EIO;
6108 }
6109
6110 return 0;
6111}
6112
6113/*
6114 * FUNCTION: wlan_hdd_cfg80211_get_txpower
6115 * This function is used to read the txpower
6116 */
6117static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
6118{
6119
6120 hdd_adapter_t *pAdapter;
6121 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6122
Jeff Johnsone7245742012-09-05 17:12:55 -07006123 ENTER();
6124
Jeff Johnson295189b2012-06-20 16:38:30 -07006125 if (NULL == pHddCtx)
6126 {
6127 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
6128 *dbm = 0;
6129 return -ENOENT;
6130 }
6131
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006132 if ( pHddCtx->isLogpInProgress )
6133 {
6134 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6135 "%s:LOGP in Progress. Ignore!!!", __func__);
6136 return -EAGAIN;
6137 }
6138
Jeff Johnson295189b2012-06-20 16:38:30 -07006139 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
6140 if (NULL == pAdapter)
6141 {
6142 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
6143 return -ENOENT;
6144 }
6145
6146 wlan_hdd_get_classAstats(pAdapter);
6147 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
6148
Jeff Johnsone7245742012-09-05 17:12:55 -07006149 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006150 return 0;
6151}
6152
6153static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
6154 u8* mac, struct station_info *sinfo)
6155{
6156 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
6157 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6158 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
6159 tANI_U8 rate_flags;
6160
6161 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6162 hdd_config_t *pCfg = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07006163
6164 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
6165 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
6166 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
6167 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
6168 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
6169 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
6170 tANI_U16 maxRate = 0;
6171 tANI_U16 myRate;
6172 tANI_U16 currentRate = 0;
6173 tANI_U8 maxSpeedMCS = 0;
6174 tANI_U8 maxMCSIdx = 0;
6175 tANI_U8 rateFlag = 1;
6176 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006177 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07006178
Jeff Johnsone7245742012-09-05 17:12:55 -07006179 ENTER();
6180
Jeff Johnson295189b2012-06-20 16:38:30 -07006181 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
6182 (0 == ssidlen))
6183 {
6184 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
6185 " Invalid ssidlen, %d", __func__, ssidlen);
6186 /*To keep GUI happy*/
6187 return 0;
6188 }
6189
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006190 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6191 {
6192 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6193 "%s:LOGP in Progress. Ignore!!!", __func__);
6194 return -EAGAIN;
6195 }
6196
Jeff Johnson295189b2012-06-20 16:38:30 -07006197 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
6198 sinfo->filled |= STATION_INFO_SIGNAL;
6199
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006200 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006201 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
6202
6203 //convert to the UI units of 100kbps
6204 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
6205
6206#ifdef LINKSPEED_DEBUG_ENABLED
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006207 pr_info("RSSI %d, RLMS %u, rate %d, rssi high %d, rssi mid %d, rssi low %d, rate_flags 0x%x\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07006208 sinfo->signal,
6209 pCfg->reportMaxLinkSpeed,
6210 myRate,
6211 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006212 (int) pCfg->linkSpeedRssiMid,
6213 (int) pCfg->linkSpeedRssiLow,
6214 (int) rate_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07006215#endif //LINKSPEED_DEBUG_ENABLED
6216
6217 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
6218 {
6219 // we do not want to necessarily report the current speed
6220 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
6221 {
6222 // report the max possible speed
6223 rssidx = 0;
6224 }
6225 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
6226 {
6227 // report the max possible speed with RSSI scaling
6228 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
6229 {
6230 // report the max possible speed
6231 rssidx = 0;
6232 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006233 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07006234 {
6235 // report middle speed
6236 rssidx = 1;
6237 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006238 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
6239 {
6240 // report middle speed
6241 rssidx = 2;
6242 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006243 else
6244 {
6245 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006246 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07006247 }
6248 }
6249 else
6250 {
6251 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
6252 hddLog(VOS_TRACE_LEVEL_ERROR,
6253 "%s: Invalid value for reportMaxLinkSpeed: %u",
6254 __func__, pCfg->reportMaxLinkSpeed);
6255 rssidx = 0;
6256 }
6257
6258 maxRate = 0;
6259
6260 /* Get Basic Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306261 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_OPERATIONAL_RATE_SET,
6262 OperationalRates, &ORLeng))
6263 {
6264 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6265 /*To keep GUI happy*/
6266 return 0;
6267 }
6268
Jeff Johnson295189b2012-06-20 16:38:30 -07006269 for (i = 0; i < ORLeng; i++)
6270 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006271 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006272 {
6273 /* Validate Rate Set */
6274 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
6275 {
6276 currentRate = supported_data_rate[j].supported_rate[rssidx];
6277 break;
6278 }
6279 }
6280 /* Update MAX rate */
6281 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6282 }
6283
6284 /* Get Extended Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306285 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
6286 ExtendedRates, &ERLeng))
6287 {
6288 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6289 /*To keep GUI happy*/
6290 return 0;
6291 }
6292
Jeff Johnson295189b2012-06-20 16:38:30 -07006293 for (i = 0; i < ERLeng; i++)
6294 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006295 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006296 {
6297 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
6298 {
6299 currentRate = supported_data_rate[j].supported_rate[rssidx];
6300 break;
6301 }
6302 }
6303 /* Update MAX rate */
6304 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6305 }
6306
6307 /* Get MCS Rate Set -- but only if we are connected at MCS
6308 rates or if we are always reporting max speed or if we have
6309 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006310 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07006311 {
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306312 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_CURRENT_MCS_SET,
6313 MCSRates, &MCSLeng))
6314 {
6315 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6316 /*To keep GUI happy*/
6317 return 0;
6318 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006319 rateFlag = 0;
6320 if (rate_flags & eHAL_TX_RATE_HT40)
6321 {
6322 rateFlag |= 1;
6323 }
6324 if (rate_flags & eHAL_TX_RATE_SGI)
6325 {
6326 rateFlag |= 2;
6327 }
6328
6329 for (i = 0; i < MCSLeng; i++)
6330 {
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006331 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
6332 for (j = 0; j < temp; j++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006333 {
6334 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
6335 {
6336 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
6337 break;
6338 }
6339 }
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006340 if ((j < temp) && (currentRate > maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006341 {
6342 maxRate = currentRate;
6343 maxSpeedMCS = 1;
6344 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
6345 }
6346 }
6347 }
6348
6349 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006350 if (((maxRate < myRate) && (0 == rssidx)) ||
6351 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006352 {
6353 maxRate = myRate;
6354 if (rate_flags & eHAL_TX_RATE_LEGACY)
6355 {
6356 maxSpeedMCS = 0;
6357 }
6358 else
6359 {
6360 maxSpeedMCS = 1;
6361 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6362 }
6363 }
6364
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006365 if ((!maxSpeedMCS) || (0 != rssidx))
Jeff Johnson295189b2012-06-20 16:38:30 -07006366 {
6367 sinfo->txrate.legacy = maxRate;
6368#ifdef LINKSPEED_DEBUG_ENABLED
6369 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
6370#endif //LINKSPEED_DEBUG_ENABLED
6371 }
6372 else
6373 {
6374 sinfo->txrate.mcs = maxMCSIdx;
6375 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6376 if (rate_flags & eHAL_TX_RATE_SGI)
6377 {
6378 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6379 }
6380 if (rate_flags & eHAL_TX_RATE_HT40)
6381 {
6382 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6383 }
6384#ifdef LINKSPEED_DEBUG_ENABLED
6385 pr_info("Reporting MCS rate %d flags %x\n",
6386 sinfo->txrate.mcs,
6387 sinfo->txrate.flags );
6388#endif //LINKSPEED_DEBUG_ENABLED
6389 }
6390 }
6391 else
6392 {
6393 // report current rate instead of max rate
6394
6395 if (rate_flags & eHAL_TX_RATE_LEGACY)
6396 {
6397 //provide to the UI in units of 100kbps
6398 sinfo->txrate.legacy = myRate;
6399#ifdef LINKSPEED_DEBUG_ENABLED
6400 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
6401#endif //LINKSPEED_DEBUG_ENABLED
6402 }
6403 else
6404 {
6405 //must be MCS
6406 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6407 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6408 if (rate_flags & eHAL_TX_RATE_SGI)
6409 {
6410 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6411 }
6412 if (rate_flags & eHAL_TX_RATE_HT40)
6413 {
6414 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6415 }
6416#ifdef LINKSPEED_DEBUG_ENABLED
6417 pr_info("Reporting actual MCS rate %d flags %x\n",
6418 sinfo->txrate.mcs,
6419 sinfo->txrate.flags );
6420#endif //LINKSPEED_DEBUG_ENABLED
6421 }
6422 }
6423 sinfo->filled |= STATION_INFO_TX_BITRATE;
6424
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006425 sinfo->tx_packets =
6426 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
6427 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
6428 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
6429 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
6430
6431 sinfo->tx_retries =
6432 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
6433 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
6434 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
6435 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
6436
6437 sinfo->tx_failed =
6438 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
6439 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
6440 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
6441 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
6442
6443 sinfo->filled |=
6444 STATION_INFO_TX_PACKETS |
6445 STATION_INFO_TX_RETRIES |
6446 STATION_INFO_TX_FAILED;
6447
6448 EXIT();
6449 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006450}
6451
6452static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
6453 struct net_device *dev, bool mode, v_SINT_t timeout)
6454{
6455 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6456 VOS_STATUS vos_status;
6457
Jeff Johnsone7245742012-09-05 17:12:55 -07006458 ENTER();
6459
Jeff Johnson295189b2012-06-20 16:38:30 -07006460 if (NULL == pAdapter)
6461 {
6462 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6463 return -ENODEV;
6464 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006465 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6466 {
6467 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6468 "%s:LOGP in Progress. Ignore!!!", __func__);
6469 return -EAGAIN;
6470 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006471
6472 /**The get power cmd from the supplicant gets updated by the nl only
6473 *on successful execution of the function call
6474 *we are oppositely mapped w.r.t mode in the driver
6475 **/
6476 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
6477
Jeff Johnsone7245742012-09-05 17:12:55 -07006478 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006479 if (VOS_STATUS_E_FAILURE == vos_status)
6480 {
6481 return -EINVAL;
6482 }
6483 return 0;
6484}
6485
6486
6487#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6488static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
6489 struct net_device *netdev,
6490 u8 key_index)
6491{
Jeff Johnsone7245742012-09-05 17:12:55 -07006492 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006493 return 0;
6494}
6495#endif //LINUX_VERSION_CODE
6496
6497#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
6498static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6499 struct net_device *dev,
6500 struct ieee80211_txq_params *params)
6501{
Jeff Johnsone7245742012-09-05 17:12:55 -07006502 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006503 return 0;
6504}
6505#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6506static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6507 struct ieee80211_txq_params *params)
6508{
Jeff Johnsone7245742012-09-05 17:12:55 -07006509 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006510 return 0;
6511}
6512#endif //LINUX_VERSION_CODE
6513
6514static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
6515 struct net_device *dev, u8 *mac)
6516{
6517 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006518 VOS_STATUS vos_status;
6519 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006520
Jeff Johnsone7245742012-09-05 17:12:55 -07006521 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006522 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6523 {
6524 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6525 return -EINVAL;
6526 }
6527
6528 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6529 {
6530 hddLog( LOGE,
6531 "%s: Wlan Load/Unload is in progress", __func__);
6532 return -EBUSY;
6533 }
6534
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006535 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6536 {
6537 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6538 "%s:LOGP in Progress. Ignore!!!", __func__);
6539 return -EAGAIN;
6540 }
6541
Jeff Johnson295189b2012-06-20 16:38:30 -07006542 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006543 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006544 )
6545 {
6546 if( NULL == mac )
6547 {
6548 v_U16_t i;
6549 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
6550 {
6551 if(pAdapter->aStaInfo[i].isUsed)
6552 {
6553 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
6554 hddLog(VOS_TRACE_LEVEL_INFO,
6555 "%s: Delete STA with MAC::"
6556 "%02x:%02x:%02x:%02x:%02x:%02x",
6557 __func__,
6558 macAddr[0], macAddr[1], macAddr[2],
6559 macAddr[3], macAddr[4], macAddr[5]);
6560 hdd_softap_sta_deauth(pAdapter, macAddr);
6561 }
6562 }
6563 }
6564 else
6565 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006566
6567 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
6568 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6569 {
6570 hddLog(VOS_TRACE_LEVEL_INFO,
6571 "%s: Skip this DEL STA as this is not used::"
6572 "%02x:%02x:%02x:%02x:%02x:%02x",
6573 __func__,
6574 mac[0], mac[1], mac[2],
6575 mac[3], mac[4], mac[5]);
6576 return -ENOENT;
6577 }
6578
6579 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
6580 {
6581 hddLog(VOS_TRACE_LEVEL_INFO,
6582 "%s: Skip this DEL STA as deauth is in progress::"
6583 "%02x:%02x:%02x:%02x:%02x:%02x",
6584 __func__,
6585 mac[0], mac[1], mac[2],
6586 mac[3], mac[4], mac[5]);
6587 return -ENOENT;
6588 }
6589
6590 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
6591
Jeff Johnson295189b2012-06-20 16:38:30 -07006592 hddLog(VOS_TRACE_LEVEL_INFO,
6593 "%s: Delete STA with MAC::"
6594 "%02x:%02x:%02x:%02x:%02x:%02x",
6595 __func__,
6596 mac[0], mac[1], mac[2],
6597 mac[3], mac[4], mac[5]);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006598
6599 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
6600 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6601 {
6602 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
6603 hddLog(VOS_TRACE_LEVEL_INFO,
6604 "%s: STA removal failed for ::"
6605 "%02x:%02x:%02x:%02x:%02x:%02x",
6606 __func__,
6607 mac[0], mac[1], mac[2],
6608 mac[3], mac[4], mac[5]);
6609 return -ENOENT;
6610 }
6611
Jeff Johnson295189b2012-06-20 16:38:30 -07006612 }
6613 }
6614
6615 EXIT();
6616
6617 return 0;
6618}
6619
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006620static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
6621 struct net_device *dev, u8 *mac, struct station_parameters *params)
6622{
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006623 int status = -EPERM;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006624#ifdef FEATURE_WLAN_TDLS
6625 u32 mask, set;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006626 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006627 mask = params->sta_flags_mask;
6628
6629 set = params->sta_flags_set;
6630
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006631#ifdef WLAN_FEATURE_TDLS_DEBUG
6632 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6633 "%s: mask 0x%x set 0x%x " MAC_ADDRESS_STR,
6634 __func__, mask, set, MAC_ADDR_ARRAY(mac));
6635#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006636
6637 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6638 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006639 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006640 }
6641 }
6642#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006643 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006644}
6645
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006646
6647#ifdef FEATURE_WLAN_LFR
6648static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006649 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006650{
6651#define MAX_PMKSAIDS_IN_CACHE 8
6652 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -07006653 static tANI_U32 i; // HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006654 tANI_U32 j=0;
6655 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6656 tHalHandle halHandle;
6657 eHalStatus result;
6658 tANI_U8 BSSIDMatched = 0;
6659
Jeff Johnsone7245742012-09-05 17:12:55 -07006660 ENTER();
6661
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006662 // Validate pAdapter
6663 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6664 {
6665 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6666 return -EINVAL;
6667 }
6668
6669 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6670 {
6671 hddLog( LOGE,
6672 "%s: Wlan Load/Unload is in progress", __func__);
6673 return -EBUSY;
6674 }
6675
6676 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6677 {
6678 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6679 "%s:LOGP in Progress. Ignore!!!", __func__);
6680 return -EAGAIN;
6681 }
6682
6683 // Retrieve halHandle
6684 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
6685
6686 for (j = 0; j < i; j++)
6687 {
6688 if(vos_mem_compare(PMKIDCache[j].BSSID,
6689 pmksa->bssid, WNI_CFG_BSSID_LEN))
6690 {
6691 /* BSSID matched previous entry. Overwrite it. */
6692 BSSIDMatched = 1;
6693 vos_mem_copy(PMKIDCache[j].BSSID,
6694 pmksa->bssid, WNI_CFG_BSSID_LEN);
6695 vos_mem_copy(PMKIDCache[j].PMKID,
6696 pmksa->pmkid,
6697 CSR_RSN_PMKID_SIZE);
6698 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006699 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006700 dump_bssid(pmksa->bssid);
6701 dump_pmkid(halHandle, pmksa->pmkid);
6702 break;
6703 }
6704 }
6705
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07006706 /* Check we compared all entries,if then take the first slot now */
6707 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
6708
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006709 if (!BSSIDMatched)
6710 {
6711 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
6712 vos_mem_copy(PMKIDCache[i].BSSID,
6713 pmksa->bssid, ETHER_ADDR_LEN);
6714 vos_mem_copy(PMKIDCache[i].PMKID,
6715 pmksa->pmkid,
6716 CSR_RSN_PMKID_SIZE);
6717 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006718 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006719 dump_bssid(pmksa->bssid);
6720 dump_pmkid(halHandle, pmksa->pmkid);
6721 // Increment the HDD Local Cache index
6722 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
6723 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
6724 }
6725
6726
6727 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
6728 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006729 // __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006730 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006731 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006732 // Finally set the PMKSA ID Cache in CSR
6733 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
6734 PMKIDCache,
6735 i );
6736 return 0;
6737}
6738
6739
6740static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006741 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006742{
Jeff Johnsone7245742012-09-05 17:12:55 -07006743 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006744 // TODO: Implement this later.
6745 return 0;
6746}
6747
6748static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
6749{
Jeff Johnsone7245742012-09-05 17:12:55 -07006750 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006751 // TODO: Implement this later.
6752 return 0;
6753}
6754#endif
6755
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006756#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6757static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
6758 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
6759{
6760 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6761 hdd_station_ctx_t *pHddStaCtx;
6762
6763 if (NULL == pAdapter)
6764 {
6765 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6766 return -ENODEV;
6767 }
6768
6769 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6770
6771 // Added for debug on reception of Re-assoc Req.
6772 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6773 {
6774 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
6775 ftie->ie_len);
6776 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
6777 }
6778
6779#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
6780 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
6781 ftie->ie_len);
6782#endif
6783
6784 // Pass the received FT IEs to SME
Gopichand Nakkala356fb102013-03-06 12:34:04 +05306785 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6786 (const u8 *)ftie->ie,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006787 ftie->ie_len);
6788 return 0;
6789}
6790#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006791
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006792#ifdef FEATURE_WLAN_TDLS
6793static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
6794 u8 *peer, u8 action_code, u8 dialog_token,
6795 u16 status_code, const u8 *buf, size_t len)
6796{
6797
6798 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6799 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006800 u8 peerMac[6];
6801 VOS_STATUS status;
Gopichand Nakkala05922802013-03-14 12:23:19 -07006802 int max_sta_failed = 0;
Hoonki Leea34dd892013-02-05 22:56:02 -08006803 int responder;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006804
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006805 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006806 {
6807 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6808 "Invalid arguments");
6809 return -EINVAL;
6810 }
6811
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006812 if (pHddCtx->isLogpInProgress)
6813 {
6814 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6815 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006816 wlan_hdd_tdls_set_link_status(pAdapter, peer, eTDLS_LINK_IDLE);
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006817 return -EBUSY;
6818 }
6819
Hoonki Lee27511902013-03-14 18:19:06 -07006820 if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006821 {
Hoonki Lee27511902013-03-14 18:19:06 -07006822 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6823 "%s: TDLS mode is disabled OR not enabled in FW."
6824 MAC_ADDRESS_STR " action %d declined.",
6825 __func__, MAC_ADDR_ARRAY(peer), action_code);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006826 return -ENOTSUPP;
6827 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006828
Hoonki Lee27511902013-03-14 18:19:06 -07006829 if ((SIR_MAC_TDLS_SETUP_RSP == action_code) ||
6830 (SIR_MAC_TDLS_DIS_RSP == action_code))
6831 {
6832 wlan_hdd_tdls_set_cap (pAdapter, peerMac, eTDLS_CAP_SUPPORTED);
6833 }
6834
6835 /* other than teardown frame, other mgmt frames are not sent if disabled */
6836 if (SIR_MAC_TDLS_TEARDOWN != action_code)
6837 {
6838 /* if tdls_mode is disabled to respond to peer's request */
6839 if (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode)
6840 {
6841 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6842 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006843 " TDLS mode is disabled. action %d declined.",
6844 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee27511902013-03-14 18:19:06 -07006845
6846 return -ENOTSUPP;
6847 }
6848 }
6849
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006850 if (WLAN_IS_TDLS_SETUP_ACTION(action_code))
6851 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006852 if (wlan_hdd_tdls_is_progress(pAdapter, peer, TRUE))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006853 {
6854 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006855 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006856 " TDLS setup is ongoing. action %d declined.",
6857 __func__, MAC_ADDR_ARRAY(peer), action_code);
6858 return -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006859 }
6860 }
6861
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006862 if (SIR_MAC_TDLS_SETUP_REQ == action_code ||
6863 SIR_MAC_TDLS_SETUP_RSP == action_code )
Lee Hoonkic1262f22013-01-24 21:59:00 -08006864 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006865 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
Lee Hoonkic1262f22013-01-24 21:59:00 -08006866 {
6867 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
6868 we return error code at 'add_station()'. Hence we have this
6869 check again in addtion to add_station().
6870 Anyway, there is no hard to double-check. */
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006871 if (SIR_MAC_TDLS_SETUP_REQ == action_code)
Lee Hoonkic1262f22013-01-24 21:59:00 -08006872 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006873 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6874 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006875 " TDLS Max peer already connected. action %d declined.",
6876 __func__, MAC_ADDR_ARRAY(peer), action_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006877 goto error;
Lee Hoonkic1262f22013-01-24 21:59:00 -08006878 }
6879 else
6880 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006881 /* maximum reached. tweak to send error code to peer and return
6882 error code to supplicant */
Lee Hoonkic1262f22013-01-24 21:59:00 -08006883 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006884 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6885 "%s: " MAC_ADDRESS_STR
6886 " TDLS Max peer already connected send response status %d",
6887 __func__, MAC_ADDR_ARRAY(peer), status_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006888 max_sta_failed = -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006889 /* fall through to send setup resp with failure status
6890 code */
Lee Hoonkic1262f22013-01-24 21:59:00 -08006891 }
6892 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006893 else
6894 {
6895 hddTdlsPeer_t *pTdlsPeer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006896 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006897 if (pTdlsPeer && (eTDLS_LINK_CONNECTED == pTdlsPeer->link_status))
6898 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006899 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006900 "%s:" MAC_ADDRESS_STR " already connected. action %d declined.",
6901 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006902 return -EPERM;
6903 }
6904 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006905 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006906 vos_mem_copy(peerMac, peer, 6);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006907
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006908#ifdef WLAN_FEATURE_TDLS_DEBUG
6909 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006910 "%s: " MAC_ADDRESS_STR " action %d, dialog_token %d status %d, len = %d",
6911 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
6912 action_code, dialog_token, status_code, len);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006913#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006914
Hoonki Leea34dd892013-02-05 22:56:02 -08006915 /*Except teardown responder will not be used so just make 0*/
6916 responder = 0;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006917 if (SIR_MAC_TDLS_TEARDOWN == action_code)
Hoonki Leea34dd892013-02-05 22:56:02 -08006918 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006919 responder = wlan_hdd_tdls_get_responder(pAdapter, peerMac);
6920 if(-1 == responder)
Hoonki Leea34dd892013-02-05 22:56:02 -08006921 {
6922 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006923 "%s: " MAC_ADDRESS_STR " peer doesn't exist dialog_token %d status %d, len = %d",
6924 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
Hoonki Leea34dd892013-02-05 22:56:02 -08006925 dialog_token, status_code, len);
6926 return -EPERM;
6927 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006928 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006929
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006930 INIT_COMPLETION(pAdapter->tdls_mgmt_comp);
6931
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006932 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
Hoonki Leea34dd892013-02-05 22:56:02 -08006933 peerMac, action_code, dialog_token, status_code, (tANI_U8 *)buf, len, responder);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006934
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006935 if (VOS_STATUS_SUCCESS != status)
6936 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006937 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6938 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006939 return -EPERM;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006940 }
6941
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006942 /* not block discovery request, as it is called from timer callback */
6943 if (SIR_MAC_TDLS_DIS_REQ != action_code)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006944 {
Pervinder Singhb4638422013-03-04 22:51:36 -08006945 long rc;
6946
6947 rc = wait_for_completion_interruptible_timeout(&pAdapter->tdls_mgmt_comp,
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006948 msecs_to_jiffies(WAIT_TIME_TDLS_MGMT));
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006949
Pervinder Singhb4638422013-03-04 22:51:36 -08006950 if ((rc <= 0) || (TRUE != pAdapter->mgmtTxCompletionStatus))
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006951 {
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006952 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pervinder Singhb4638422013-03-04 22:51:36 -08006953 "%s: Mgmt Tx Completion failed status %ld TxCompletion %lu",
6954 __func__, rc, pAdapter->mgmtTxCompletionStatus);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006955 return -EPERM;
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006956 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006957 }
6958
Gopichand Nakkala05922802013-03-14 12:23:19 -07006959 if (max_sta_failed)
6960 return max_sta_failed;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006961
Hoonki Leea34dd892013-02-05 22:56:02 -08006962 if (SIR_MAC_TDLS_SETUP_RSP == action_code)
6963 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006964 wlan_hdd_tdls_set_responder(pAdapter, peerMac, TRUE);
Hoonki Leea34dd892013-02-05 22:56:02 -08006965 }
6966 else if (SIR_MAC_TDLS_SETUP_CNF == action_code)
6967 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006968 wlan_hdd_tdls_set_responder(pAdapter, peerMac, FALSE);
Hoonki Leea34dd892013-02-05 22:56:02 -08006969 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006970
6971 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07006972error:
6973 /* max_sta_failed ; we didn't set to CONNECTING for this case,
6974 because we already know that this transaction will be failed,
6975 but we weren't sure if supplicant call DISABLE_LINK or not. So,
6976 to be safe, do not change the state mahine.
6977 */
6978 if(max_sta_failed == 0 &&
6979 (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
6980 wlan_hdd_tdls_set_link_status(pAdapter, peerMac, eTDLS_LINK_IDLE);
6981 return -EPERM;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006982}
6983
6984static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
6985 u8 *peer, enum nl80211_tdls_operation oper)
6986{
6987 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6988 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006989#ifdef WLAN_FEATURE_TDLS_DEBUG
6990 const char *tdls_oper_str[]= {
6991 "NL80211_TDLS_DISCOVERY_REQ",
6992 "NL80211_TDLS_SETUP",
6993 "NL80211_TDLS_TEARDOWN",
6994 "NL80211_TDLS_ENABLE_LINK",
6995 "NL80211_TDLS_DISABLE_LINK",
6996 "NL80211_TDLS_UNKONW_OPER"};
6997#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006998
6999 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
7000 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007001 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007002 "Invalid arguments");
7003 return -EINVAL;
7004 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007005
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08007006 if (pHddCtx->isLogpInProgress)
7007 {
7008 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7009 "%s:LOGP in Progress. Ignore!!!", __func__);
7010 return -EBUSY;
7011 }
7012
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007013#ifdef WLAN_FEATURE_TDLS_DEBUG
7014 if((int)oper > 4)
7015 oper = 5;
7016
7017 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007018 "%s: " MAC_ADDRESS_STR " %d (%s) ", "tdls_oper",
7019 MAC_ADDR_ARRAY(peer), (int)oper,
7020 tdls_oper_str[(int)oper]);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007021#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007022
7023 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007024 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007025 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007026 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007027 "TDLS Disabled in INI OR not enabled in FW.\
7028 Cannot process TDLS commands \n");
7029 return -ENOTSUPP;
7030 }
7031
7032 switch (oper) {
7033 case NL80211_TDLS_ENABLE_LINK:
7034 {
Hoonki Lee387663d2013-02-05 18:08:43 -08007035 hddTdlsPeer_t *pTdlsPeer;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007036 VOS_STATUS status;
7037
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007038 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007039
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007040 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
7041 "%s: TDLS_LINK_ENABLE " MAC_ADDRESS_STR,
7042 __func__, MAC_ADDR_ARRAY(peer));
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007043
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007044 if ( NULL == pTdlsPeer ) {
7045 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_hdd_tdls_find_peer "
7046 MAC_ADDRESS_STR " failed",
7047 __func__, MAC_ADDR_ARRAY(peer));
7048 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007049 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007050
7051 if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status)
7052 {
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007053 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007054 /* start TDLS client registration with TL */
7055 status = hdd_roamRegisterTDLSSTA( pAdapter, peer, pTdlsPeer->staId, pTdlsPeer->signature);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007056 if (VOS_STATUS_SUCCESS == status)
7057 {
7058 wlan_hdd_tdls_increment_peer_count(pAdapter);
7059 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007060 wlan_hdd_tdls_check_bmps(pAdapter);
7061 }
7062
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007063 }
7064 break;
7065 case NL80211_TDLS_DISABLE_LINK:
Lee Hoonkic1262f22013-01-24 21:59:00 -08007066 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007067 hddTdlsPeer_t *curr_peer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007068
7069 if(NULL != curr_peer)
Lee Hoonkic1262f22013-01-24 21:59:00 -08007070 {
7071 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
7072 pAdapter->sessionId, peer );
Gopichand Nakkala8b00c632013-03-08 19:47:52 -08007073 wlan_hdd_tdls_set_peer_link_status(curr_peer, eTDLS_LINK_IDLE);
Lee Hoonkic1262f22013-01-24 21:59:00 -08007074 }
7075 else
7076 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007077 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7078 "%s: TDLS Peer Station doesn't exist.", __func__);
Lee Hoonkic1262f22013-01-24 21:59:00 -08007079 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08007080 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007081 break;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007082 case NL80211_TDLS_TEARDOWN:
7083 case NL80211_TDLS_SETUP:
7084 case NL80211_TDLS_DISCOVERY_REQ:
7085 /* We don't support in-driver setup/teardown/discovery */
7086 return -ENOTSUPP;
7087 default:
7088 return -ENOTSUPP;
7089 }
7090 return 0;
7091}
Chilam NG571c65a2013-01-19 12:27:36 +05307092
7093int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
7094 struct net_device *dev, u8 *peer)
7095{
7096 hddLog(VOS_TRACE_LEVEL_INFO, "tdls send discover req: %x %x %x %x %x %x",
7097 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5]);
7098
7099 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
7100 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
7101}
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007102#endif
7103
Jeff Johnson295189b2012-06-20 16:38:30 -07007104/* cfg80211_ops */
7105static struct cfg80211_ops wlan_hdd_cfg80211_ops =
7106{
7107 .add_virtual_intf = wlan_hdd_add_virtual_intf,
7108 .del_virtual_intf = wlan_hdd_del_virtual_intf,
7109 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
7110 .change_station = wlan_hdd_change_station,
7111#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
7112 .add_beacon = wlan_hdd_cfg80211_add_beacon,
7113 .del_beacon = wlan_hdd_cfg80211_del_beacon,
7114 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007115#else
7116 .start_ap = wlan_hdd_cfg80211_start_ap,
7117 .change_beacon = wlan_hdd_cfg80211_change_beacon,
7118 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07007119#endif
7120 .change_bss = wlan_hdd_cfg80211_change_bss,
7121 .add_key = wlan_hdd_cfg80211_add_key,
7122 .get_key = wlan_hdd_cfg80211_get_key,
7123 .del_key = wlan_hdd_cfg80211_del_key,
7124 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08007125#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07007126 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08007127#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007128 .scan = wlan_hdd_cfg80211_scan,
7129 .connect = wlan_hdd_cfg80211_connect,
7130 .disconnect = wlan_hdd_cfg80211_disconnect,
7131 .join_ibss = wlan_hdd_cfg80211_join_ibss,
7132 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
7133 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
7134 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
7135 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
Jeff Johnson295189b2012-06-20 16:38:30 -07007136 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
7137 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
7138 .mgmt_tx = wlan_hdd_action,
7139#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7140 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
7141 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
7142 .set_txq_params = wlan_hdd_set_txq_params,
7143#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007144 .get_station = wlan_hdd_cfg80211_get_station,
7145 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
7146 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007147 .add_station = wlan_hdd_cfg80211_add_station,
7148#ifdef FEATURE_WLAN_LFR
7149 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
7150 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
7151 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
7152#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007153#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
7154 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
7155#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007156#ifdef FEATURE_WLAN_TDLS
7157 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
7158 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
7159#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007160};
7161