blob: 58fffebaf2ef668aca056fd7af794f4507134e4a [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
54/**=========================================================================
55
56 EDIT HISTORY FOR FILE
57
58
59 This section contains comments describing changes made to the module.
60 Notice that changes are listed in reverse chronological order.
61
62
63 $Header:$ $DateTime: $ $Author: $
64
65
66 when who what, where, why
67 -------- --- --------------------------------------------------------
68 21/12/09 Ashwani Created module.
69
70 07/06/10 Kumar Deepak Implemented cfg80211 callbacks for ANDROID
71 Ganesh K
72 ==========================================================================*/
73
Jeff Johnson295189b2012-06-20 16:38:30 -070074
75#include <linux/version.h>
76#include <linux/module.h>
77#include <linux/kernel.h>
78#include <linux/init.h>
79#include <linux/wireless.h>
80#include <wlan_hdd_includes.h>
81#include <net/arp.h>
82#include <net/cfg80211.h>
83#include <linux/wireless.h>
84#include <wlan_hdd_wowl.h>
85#include <aniGlobal.h>
86#include "ccmApi.h"
87#include "sirParams.h"
88#include "dot11f.h"
89#include "wlan_hdd_assoc.h"
90#include "wlan_hdd_wext.h"
91#include "sme_Api.h"
92#include "wlan_hdd_p2p.h"
93#include "wlan_hdd_cfg80211.h"
94#include "wlan_hdd_hostapd.h"
95#include "sapInternal.h"
96#include "wlan_hdd_softap_tx_rx.h"
97#include "wlan_hdd_main.h"
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +053098#include "wlan_hdd_assoc.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070099#ifdef WLAN_BTAMP_FEATURE
100#include "bap_hdd_misc.h"
101#endif
102#include <qc_sap_ioctl.h>
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800103#ifdef FEATURE_WLAN_TDLS
104#include "wlan_hdd_tdls.h"
105#endif
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +0530106#include "wlan_nv.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700107
108#define g_mode_rates_size (12)
109#define a_mode_rates_size (8)
110#define FREQ_BASE_80211G (2407)
111#define FREQ_BAND_DIFF_80211G (5)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700112#define MAX_SCAN_SSID 9
Jeff Johnson295189b2012-06-20 16:38:30 -0700113#define GET_IE_LEN_IN_BSS_DESC(lenInBss) ( lenInBss + sizeof(lenInBss) - \
114 ((int) OFFSET_OF( tSirBssDescription, ieFields)))
115
116#define HDD2GHZCHAN(freq, chan, flag) { \
117 .band = IEEE80211_BAND_2GHZ, \
118 .center_freq = (freq), \
119 .hw_value = (chan),\
120 .flags = (flag), \
121 .max_antenna_gain = 0 ,\
122 .max_power = 30, \
123}
124
125#define HDD5GHZCHAN(freq, chan, flag) { \
126 .band = IEEE80211_BAND_5GHZ, \
127 .center_freq = (freq), \
128 .hw_value = (chan),\
129 .flags = (flag), \
130 .max_antenna_gain = 0 ,\
131 .max_power = 30, \
132}
133
134#define HDD_G_MODE_RATETAB(rate, rate_id, flag)\
135{\
136 .bitrate = rate, \
137 .hw_value = rate_id, \
138 .flags = flag, \
139}
140
Lee Hoonkic1262f22013-01-24 21:59:00 -0800141#ifndef WLAN_FEATURE_TDLS_DEBUG
142#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_INFO
143#else
144#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_ERROR
145#endif
146
Gopichand Nakkala356fb102013-03-06 12:34:04 +0530147#ifdef WLAN_FEATURE_VOWIFI_11R
148#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
149#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
150#endif
151
Jeff Johnson295189b2012-06-20 16:38:30 -0700152static const u32 hdd_cipher_suites[] =
153{
154 WLAN_CIPHER_SUITE_WEP40,
155 WLAN_CIPHER_SUITE_WEP104,
156 WLAN_CIPHER_SUITE_TKIP,
157#ifdef FEATURE_WLAN_CCX
158#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
159 WLAN_CIPHER_SUITE_KRK,
160 WLAN_CIPHER_SUITE_CCMP,
161#else
162 WLAN_CIPHER_SUITE_CCMP,
163#endif
164#ifdef FEATURE_WLAN_WAPI
165 WLAN_CIPHER_SUITE_SMS4,
166#endif
Chet Lanctot186b5732013-03-18 10:26:30 -0700167#ifdef WLAN_FEATURE_11W
168 WLAN_CIPHER_SUITE_AES_CMAC,
169#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700170};
171
172static inline int is_broadcast_ether_addr(const u8 *addr)
173{
174 return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&
175 (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
176}
177
178static struct ieee80211_channel hdd_channels_2_4_GHZ[] =
179{
180 HDD2GHZCHAN(2412, 1, 0) ,
181 HDD2GHZCHAN(2417, 2, 0) ,
182 HDD2GHZCHAN(2422, 3, 0) ,
183 HDD2GHZCHAN(2427, 4, 0) ,
184 HDD2GHZCHAN(2432, 5, 0) ,
185 HDD2GHZCHAN(2437, 6, 0) ,
186 HDD2GHZCHAN(2442, 7, 0) ,
187 HDD2GHZCHAN(2447, 8, 0) ,
188 HDD2GHZCHAN(2452, 9, 0) ,
189 HDD2GHZCHAN(2457, 10, 0) ,
190 HDD2GHZCHAN(2462, 11, 0) ,
191 HDD2GHZCHAN(2467, 12, 0) ,
192 HDD2GHZCHAN(2472, 13, 0) ,
193 HDD2GHZCHAN(2484, 14, 0) ,
194};
195
Jeff Johnson295189b2012-06-20 16:38:30 -0700196static struct ieee80211_channel hdd_social_channels_2_4_GHZ[] =
197{
198 HDD2GHZCHAN(2412, 1, 0) ,
199 HDD2GHZCHAN(2437, 6, 0) ,
200 HDD2GHZCHAN(2462, 11, 0) ,
201};
Jeff Johnson295189b2012-06-20 16:38:30 -0700202
203static struct ieee80211_channel hdd_channels_5_GHZ[] =
204{
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700205 HDD5GHZCHAN(4920, 240, 0) ,
206 HDD5GHZCHAN(4940, 244, 0) ,
207 HDD5GHZCHAN(4960, 248, 0) ,
208 HDD5GHZCHAN(4980, 252, 0) ,
209 HDD5GHZCHAN(5040, 208, 0) ,
210 HDD5GHZCHAN(5060, 212, 0) ,
211 HDD5GHZCHAN(5080, 216, 0) ,
Jeff Johnson295189b2012-06-20 16:38:30 -0700212 HDD5GHZCHAN(5180, 36, 0) ,
213 HDD5GHZCHAN(5200, 40, 0) ,
214 HDD5GHZCHAN(5220, 44, 0) ,
215 HDD5GHZCHAN(5240, 48, 0) ,
216 HDD5GHZCHAN(5260, 52, 0) ,
217 HDD5GHZCHAN(5280, 56, 0) ,
218 HDD5GHZCHAN(5300, 60, 0) ,
219 HDD5GHZCHAN(5320, 64, 0) ,
220 HDD5GHZCHAN(5500,100, 0) ,
221 HDD5GHZCHAN(5520,104, 0) ,
222 HDD5GHZCHAN(5540,108, 0) ,
223 HDD5GHZCHAN(5560,112, 0) ,
224 HDD5GHZCHAN(5580,116, 0) ,
225 HDD5GHZCHAN(5600,120, 0) ,
226 HDD5GHZCHAN(5620,124, 0) ,
227 HDD5GHZCHAN(5640,128, 0) ,
228 HDD5GHZCHAN(5660,132, 0) ,
229 HDD5GHZCHAN(5680,136, 0) ,
230 HDD5GHZCHAN(5700,140, 0) ,
231 HDD5GHZCHAN(5745,149, 0) ,
232 HDD5GHZCHAN(5765,153, 0) ,
233 HDD5GHZCHAN(5785,157, 0) ,
234 HDD5GHZCHAN(5805,161, 0) ,
235 HDD5GHZCHAN(5825,165, 0) ,
236};
237
238static struct ieee80211_rate g_mode_rates[] =
239{
240 HDD_G_MODE_RATETAB(10, 0x1, 0),
241 HDD_G_MODE_RATETAB(20, 0x2, 0),
242 HDD_G_MODE_RATETAB(55, 0x4, 0),
243 HDD_G_MODE_RATETAB(110, 0x8, 0),
244 HDD_G_MODE_RATETAB(60, 0x10, 0),
245 HDD_G_MODE_RATETAB(90, 0x20, 0),
246 HDD_G_MODE_RATETAB(120, 0x40, 0),
247 HDD_G_MODE_RATETAB(180, 0x80, 0),
248 HDD_G_MODE_RATETAB(240, 0x100, 0),
249 HDD_G_MODE_RATETAB(360, 0x200, 0),
250 HDD_G_MODE_RATETAB(480, 0x400, 0),
251 HDD_G_MODE_RATETAB(540, 0x800, 0),
252};
253
254static struct ieee80211_rate a_mode_rates[] =
255{
256 HDD_G_MODE_RATETAB(60, 0x10, 0),
257 HDD_G_MODE_RATETAB(90, 0x20, 0),
258 HDD_G_MODE_RATETAB(120, 0x40, 0),
259 HDD_G_MODE_RATETAB(180, 0x80, 0),
260 HDD_G_MODE_RATETAB(240, 0x100, 0),
261 HDD_G_MODE_RATETAB(360, 0x200, 0),
262 HDD_G_MODE_RATETAB(480, 0x400, 0),
263 HDD_G_MODE_RATETAB(540, 0x800, 0),
264};
265
266static struct ieee80211_supported_band wlan_hdd_band_2_4_GHZ =
267{
268 .channels = hdd_channels_2_4_GHZ,
269 .n_channels = ARRAY_SIZE(hdd_channels_2_4_GHZ),
270 .band = IEEE80211_BAND_2GHZ,
271 .bitrates = g_mode_rates,
272 .n_bitrates = g_mode_rates_size,
273 .ht_cap.ht_supported = 1,
274 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
275 | IEEE80211_HT_CAP_GRN_FLD
276 | IEEE80211_HT_CAP_DSSSCCK40
277 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
278 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
279 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
280 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
281 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
282 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
283};
284
Jeff Johnson295189b2012-06-20 16:38:30 -0700285static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_GHZ =
286{
287 .channels = hdd_social_channels_2_4_GHZ,
288 .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_GHZ),
289 .band = IEEE80211_BAND_2GHZ,
290 .bitrates = g_mode_rates,
291 .n_bitrates = g_mode_rates_size,
292 .ht_cap.ht_supported = 1,
293 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
294 | IEEE80211_HT_CAP_GRN_FLD
295 | IEEE80211_HT_CAP_DSSSCCK40
296 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
297 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
298 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
299 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
300 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
301 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
302};
Jeff Johnson295189b2012-06-20 16:38:30 -0700303
304static struct ieee80211_supported_band wlan_hdd_band_5_GHZ =
305{
306 .channels = hdd_channels_5_GHZ,
307 .n_channels = ARRAY_SIZE(hdd_channels_5_GHZ),
308 .band = IEEE80211_BAND_5GHZ,
309 .bitrates = a_mode_rates,
310 .n_bitrates = a_mode_rates_size,
311 .ht_cap.ht_supported = 1,
312 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
313 | IEEE80211_HT_CAP_GRN_FLD
314 | IEEE80211_HT_CAP_DSSSCCK40
315 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
316 | IEEE80211_HT_CAP_SGI_40
317 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
318 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
319 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
320 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
321 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
322 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
323};
324
325/* This structure contain information what kind of frame are expected in
326 TX/RX direction for each kind of interface */
327static const struct ieee80211_txrx_stypes
328wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
329 [NL80211_IFTYPE_STATION] = {
330 .tx = 0xffff,
331 .rx = BIT(SIR_MAC_MGMT_ACTION) |
332 BIT(SIR_MAC_MGMT_PROBE_REQ),
333 },
334 [NL80211_IFTYPE_AP] = {
335 .tx = 0xffff,
336 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
337 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
338 BIT(SIR_MAC_MGMT_PROBE_REQ) |
339 BIT(SIR_MAC_MGMT_DISASSOC) |
340 BIT(SIR_MAC_MGMT_AUTH) |
341 BIT(SIR_MAC_MGMT_DEAUTH) |
342 BIT(SIR_MAC_MGMT_ACTION),
343 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700344 [NL80211_IFTYPE_P2P_CLIENT] = {
345 .tx = 0xffff,
346 .rx = BIT(SIR_MAC_MGMT_ACTION) |
347 BIT(SIR_MAC_MGMT_PROBE_REQ),
348 },
349 [NL80211_IFTYPE_P2P_GO] = {
350 /* This is also same as for SoftAP */
351 .tx = 0xffff,
352 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
353 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
354 BIT(SIR_MAC_MGMT_PROBE_REQ) |
355 BIT(SIR_MAC_MGMT_DISASSOC) |
356 BIT(SIR_MAC_MGMT_AUTH) |
357 BIT(SIR_MAC_MGMT_DEAUTH) |
358 BIT(SIR_MAC_MGMT_ACTION),
359 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700360};
361
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800362#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800363static const struct ieee80211_iface_limit
364wlan_hdd_iface_limit[] = {
365 {
Sunil Ravia72c3992013-01-31 06:12:22 -0800366 /* max = 3 ; Our driver create two interfaces during driver init
367 * wlan0 and p2p0 interfaces. p2p0 is considered as station
368 * interface until a group is formed. In JB architecture, once the
369 * group is formed, interface type of p2p0 is changed to P2P GO or
370 * Client.
371 * When supplicant remove the group, it first issue a set interface
372 * cmd to change the mode back to Station. In JB this works fine as
373 * we advertize two station type interface during driver init.
374 * Some vendors create separate interface for P2P GO/Client,
375 * after group formation(Third one). But while group remove
376 * supplicant first tries to change the mode(3rd interface) to STATION
377 * But as we advertized only two sta type interfaces nl80211 was
378 * returning error for the third one which was leading to failure in
379 * delete interface. Ideally while removing the group, supplicant
380 * should not try to change the 3rd interface mode to Station type.
381 * Till we get a fix in wpa_supplicant, we advertize max STA
382 * interface type to 3
383 */
384 .max = 3,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800385 .types = BIT(NL80211_IFTYPE_STATION),
386 },
387 {
388 .max = 1,
389 .types = BIT(NL80211_IFTYPE_AP),
390 },
391 {
392 .max = 1,
393 .types = BIT(NL80211_IFTYPE_P2P_GO) |
394 BIT(NL80211_IFTYPE_P2P_CLIENT),
395 },
396};
397
398/* By default, only single channel concurrency is allowed */
399static struct ieee80211_iface_combination
400wlan_hdd_iface_combination = {
401 .limits = wlan_hdd_iface_limit,
402 .num_different_channels = 1,
Sunil Ravia72c3992013-01-31 06:12:22 -0800403 /*
404 * max = WLAN_MAX_INTERFACES ; JellyBean architecture creates wlan0
405 * and p2p0 interfaces during driver init
406 * Some vendors create separate interface for P2P operations.
407 * wlan0: STA interface
408 * p2p0: P2P Device interface, action frames goes
409 * through this interface.
410 * p2p-xx: P2P interface, After GO negotiation this interface is
411 * created for p2p operations(GO/CLIENT interface).
412 */
413 .max_interfaces = WLAN_MAX_INTERFACES,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800414 .n_limits = ARRAY_SIZE(wlan_hdd_iface_limit),
415 .beacon_int_infra_match = false,
416};
417#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800418
Jeff Johnson295189b2012-06-20 16:38:30 -0700419static struct cfg80211_ops wlan_hdd_cfg80211_ops;
420
421/* Data rate 100KBPS based on IE Index */
422struct index_data_rate_type
423{
424 v_U8_t beacon_rate_index;
425 v_U16_t supported_rate[4];
426};
427
428/* 11B, 11G Rate table include Basic rate and Extended rate
429 The IDX field is the rate index
430 The HI field is the rate when RSSI is strong or being ignored
431 (in this case we report actual rate)
432 The MID field is the rate when RSSI is moderate
433 (in this case we cap 11b rates at 5.5 and 11g rates at 24)
434 The LO field is the rate when RSSI is low
435 (in this case we don't report rates, actual current rate used)
436 */
437static const struct
438{
439 v_U8_t beacon_rate_index;
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700440 v_U16_t supported_rate[4];
Jeff Johnson295189b2012-06-20 16:38:30 -0700441} supported_data_rate[] =
442{
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700443/* IDX HI HM LM LO (RSSI-based index */
444 {2, { 10, 10, 10, 0}},
445 {4, { 20, 20, 10, 0}},
446 {11, { 55, 20, 10, 0}},
447 {12, { 60, 55, 20, 0}},
448 {18, { 90, 55, 20, 0}},
449 {22, {110, 55, 20, 0}},
450 {24, {120, 90, 60, 0}},
451 {36, {180, 120, 60, 0}},
452 {44, {220, 180, 60, 0}},
453 {48, {240, 180, 90, 0}},
454 {66, {330, 180, 90, 0}},
455 {72, {360, 240, 90, 0}},
456 {96, {480, 240, 120, 0}},
457 {108, {540, 240, 120, 0}}
Jeff Johnson295189b2012-06-20 16:38:30 -0700458};
459
460/* MCS Based rate table */
461static struct index_data_rate_type supported_mcs_rate[] =
462{
463/* MCS L20 L40 S20 S40 */
464 {0, {65, 135, 72, 150}},
465 {1, {130, 270, 144, 300}},
466 {2, {195, 405, 217, 450}},
467 {3, {260, 540, 289, 600}},
468 {4, {390, 810, 433, 900}},
469 {5, {520, 1080, 578, 1200}},
470 {6, {585, 1215, 650, 1350}},
471 {7, {650, 1350, 722, 1500}}
472};
473
474extern struct net_device_ops net_ops_struct;
475
476/*
477 * FUNCTION: wlan_hdd_cfg80211_init
478 * This function is called by hdd_wlan_startup()
479 * during initialization.
480 * This function is used to initialize and register wiphy structure.
481 */
482struct wiphy *wlan_hdd_cfg80211_init(int priv_size)
483{
484 struct wiphy *wiphy;
485 ENTER();
486
487 /*
488 * Create wiphy device
489 */
490 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
491
492 if (!wiphy)
493 {
494 /* Print error and jump into err label and free the memory */
495 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__);
496 return NULL;
497 }
498
499 return wiphy;
500}
501
502/*
503 * FUNCTION: wlan_hdd_cfg80211_update_band
504 * This function is called from the supplicant through a
505 * private ioctl to change the band value
506 */
507int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
508{
Jeff Johnsone7245742012-09-05 17:12:55 -0700509 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700510 switch(eBand)
511 {
512 case eCSR_BAND_24:
513 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
514 wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
515 break;
516 case eCSR_BAND_5G:
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700517 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700518 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
519 break;
520 case eCSR_BAND_ALL:
521 default:
522 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
523 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
524 }
525 return 0;
526}
527/*
528 * FUNCTION: wlan_hdd_cfg80211_init
529 * This function is called by hdd_wlan_startup()
530 * during initialization.
531 * This function is used to initialize and register wiphy structure.
532 */
533int wlan_hdd_cfg80211_register(struct device *dev,
534 struct wiphy *wiphy,
535 hdd_config_t *pCfg
536 )
537{
Jeff Johnsone7245742012-09-05 17:12:55 -0700538 ENTER();
539
Jeff Johnson295189b2012-06-20 16:38:30 -0700540 /* Now bind the underlying wlan device with wiphy */
541 set_wiphy_dev(wiphy, dev);
542
543 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
544
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700545 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700546
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700547#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700548 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
549 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
550 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
Jeff Johnsone7245742012-09-05 17:12:55 -0700551 | WIPHY_FLAG_OFFCHAN_TX;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700552#endif
James Zmuda77fb5ae2013-01-29 08:00:17 -0800553#ifdef FEATURE_WLAN_LFR
554 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
555#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800556#ifdef FEATURE_WLAN_TDLS
557 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
558 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
559#endif
560
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700561 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
562 driver can still register regulatory callback and
563 it will get CRDA setting in wiphy->band[], but
564 driver need to determine what to do with both
565 regulatory settings */
566 wiphy->reg_notifier = wlan_hdd_crda_reg_notifier;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700567
Jeff Johnson295189b2012-06-20 16:38:30 -0700568 wiphy->max_scan_ssids = MAX_SCAN_SSID;
569
570 wiphy->max_scan_ie_len = 200 ; //TODO: define a macro
571
572 /* Supports STATION & AD-HOC modes right now */
573 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
574 | BIT(NL80211_IFTYPE_ADHOC)
Jeff Johnson295189b2012-06-20 16:38:30 -0700575 | BIT(NL80211_IFTYPE_P2P_CLIENT)
576 | BIT(NL80211_IFTYPE_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -0700577 | BIT(NL80211_IFTYPE_AP);
578
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800579#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800580 if( pCfg->enableMCC )
581 {
582 /* Currently, supports up to two channels */
583 wlan_hdd_iface_combination.num_different_channels = 2;
584
585 if( !pCfg->allowMCCGODiffBI )
586 wlan_hdd_iface_combination.beacon_int_infra_match = true;
587
588 }
589 wiphy->iface_combinations = &wlan_hdd_iface_combination;
590 wiphy->n_iface_combinations = 1;
591#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800592
Jeff Johnson295189b2012-06-20 16:38:30 -0700593 /* Before registering we need to update the ht capabilitied based
594 * on ini values*/
595 if( !pCfg->ShortGI20MhzEnable )
596 {
597 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
598 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
599 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
600 }
601
602 if( !pCfg->ShortGI40MhzEnable )
603 {
604 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
605 }
606
607 if( !pCfg->nChannelBondingMode5GHz )
608 {
609 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
610 }
611
612 /*Initialize band capability*/
613 switch(pCfg->nBandCapability)
614 {
615 case eCSR_BAND_24:
616 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
617 break;
618 case eCSR_BAND_5G:
Jeff Johnson295189b2012-06-20 16:38:30 -0700619 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700620 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
621 break;
622 case eCSR_BAND_ALL:
623 default:
624 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
625 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
626 }
627 /*Initialise the supported cipher suite details*/
628 wiphy->cipher_suites = hdd_cipher_suites;
629 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
630
631 /*signal strength in mBm (100*dBm) */
632 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
633
634#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -0700635 wiphy->max_remain_on_channel_duration = 1000;
636#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700637
638 /* Register our wiphy dev with cfg80211 */
639 if (0 > wiphy_register(wiphy))
640 {
641 /* print eror */
642 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
643 return -EIO;
644 }
645
646 EXIT();
647 return 0;
648}
649
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700650/* In this function we will try to get default country code from crda.
651 If the gCrdaDefaultCountryCode is configured in ini file,
652 we will try to call user space crda to get the regulatory settings for
653 that country. We will timeout if we can't get it from crda.
654 It's called by hdd_wlan_startup() after wlan_hdd_cfg80211_register.
655*/
656int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg)
657{
658 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
659 if (memcmp(pCfg->crdaDefaultCountryCode,
660 CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) != 0)
661 {
662 init_completion(&pHddCtx->driver_crda_req);
663 regulatory_hint(wiphy, pCfg->crdaDefaultCountryCode);
664 wait_for_completion_interruptible_timeout(&pHddCtx->driver_crda_req,
665 CRDA_WAIT_TIME);
666 }
667 return 0;
668}
669
Jeff Johnson295189b2012-06-20 16:38:30 -0700670/* In this function we will do all post VOS start initialization.
671 In this function we will register for all frame in which supplicant
672 is interested.
673*/
674void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
675{
Jeff Johnson295189b2012-06-20 16:38:30 -0700676 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
677 /* Register for all P2P action, public action etc frames */
678 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
679
Jeff Johnsone7245742012-09-05 17:12:55 -0700680 ENTER();
681
Jeff Johnson295189b2012-06-20 16:38:30 -0700682 /* Right now we are registering these frame when driver is getting
683 initialized. Once we will move to 2.6.37 kernel, in which we have
684 frame register ops, we will move this code as a part of that */
685 /* GAS Initial Request */
686 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
687 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
688
689 /* GAS Initial Response */
690 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
691 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
692
693 /* GAS Comeback Request */
694 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
695 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
696
697 /* GAS Comeback Response */
698 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
699 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
700
701 /* P2P Public Action */
702 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
703 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
704 P2P_PUBLIC_ACTION_FRAME_SIZE );
705
706 /* P2P Action */
707 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
708 (v_U8_t*)P2P_ACTION_FRAME,
709 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -0700710
711#ifdef WLAN_FEATURE_11W
712 /* SA Query Response Action Frame */
713 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
714 (v_U8_t*)SA_QUERY_FRAME_RSP,
715 SA_QUERY_FRAME_RSP_SIZE );
716#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -0700717}
718
719void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
720{
Jeff Johnson295189b2012-06-20 16:38:30 -0700721 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
722 /* Register for all P2P action, public action etc frames */
723 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
724
Jeff Johnsone7245742012-09-05 17:12:55 -0700725 ENTER();
726
Jeff Johnson295189b2012-06-20 16:38:30 -0700727 /* Right now we are registering these frame when driver is getting
728 initialized. Once we will move to 2.6.37 kernel, in which we have
729 frame register ops, we will move this code as a part of that */
730 /* GAS Initial Request */
731
732 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
733 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
734
735 /* GAS Initial Response */
736 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
737 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
738
739 /* GAS Comeback Request */
740 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
741 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
742
743 /* GAS Comeback Response */
744 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
745 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
746
747 /* P2P Public Action */
748 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
749 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
750 P2P_PUBLIC_ACTION_FRAME_SIZE );
751
752 /* P2P Action */
753 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
754 (v_U8_t*)P2P_ACTION_FRAME,
755 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -0700756
757#ifdef WLAN_FEATURE_11W
758 /* SA Query Response Action Frame */
759 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
760 (v_U8_t*)SA_QUERY_FRAME_RSP,
761 SA_QUERY_FRAME_RSP_SIZE );
762#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -0700763}
764
765#ifdef FEATURE_WLAN_WAPI
766void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
767 const u8 *mac_addr, u8 *key , int key_Len)
768{
769 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
770 tCsrRoamSetKey setKey;
771 v_BOOL_t isConnected = TRUE;
772 int status = 0;
773 v_U32_t roamId= 0xFF;
774 tANI_U8 *pKeyPtr = NULL;
775 int n = 0;
776
777 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
778 __func__,pAdapter->device_mode);
779
Gopichand Nakkalae7480202013-02-11 15:24:22 +0530780 vos_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Jeff Johnson295189b2012-06-20 16:38:30 -0700781 setKey.keyId = key_index; // Store Key ID
782 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
783 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
784 setKey.paeRole = 0 ; // the PAE role
785 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
786 {
787 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
788 }
789 else
790 {
791 isConnected = hdd_connIsConnected(pHddStaCtx);
792 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
793 }
794 setKey.keyLength = key_Len;
795 pKeyPtr = setKey.Key;
796 memcpy( pKeyPtr, key, key_Len);
797
798 hddLog(VOS_TRACE_LEVEL_INFO,"\n%s: WAPI KEY LENGTH:0x%04x",
799 __func__, key_Len);
800 for (n = 0 ; n < key_Len; n++)
801 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
802 __func__,n,setKey.Key[n]);
803
804 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
805 if ( isConnected )
806 {
807 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
808 pAdapter->sessionId, &setKey, &roamId );
809 }
810 if ( status != 0 )
811 {
812 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
813 "[%4d] sme_RoamSetKey returned ERROR status= %d",
814 __LINE__, status );
815 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
816 }
817}
818#endif /* FEATURE_WLAN_WAPI*/
819
820#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
821int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
822 beacon_data_t **ppBeacon,
823 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700824#else
825int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
826 beacon_data_t **ppBeacon,
827 struct cfg80211_beacon_data *params,
828 int dtim_period)
829#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700830{
831 int size;
832 beacon_data_t *beacon = NULL;
833 beacon_data_t *old = NULL;
834 int head_len,tail_len;
835
Jeff Johnsone7245742012-09-05 17:12:55 -0700836 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700837 if (params->head && !params->head_len)
838 return -EINVAL;
839
840 old = pAdapter->sessionCtx.ap.beacon;
841
842 if (!params->head && !old)
843 return -EINVAL;
844
845 if (params->tail && !params->tail_len)
846 return -EINVAL;
847
848#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
849 /* Kernel 3.0 is not updating dtim_period for set beacon */
850 if (!params->dtim_period)
851 return -EINVAL;
852#endif
853
854 if(params->head)
855 head_len = params->head_len;
856 else
857 head_len = old->head_len;
858
859 if(params->tail || !old)
860 tail_len = params->tail_len;
861 else
862 tail_len = old->tail_len;
863
864 size = sizeof(beacon_data_t) + head_len + tail_len;
865
866 beacon = kzalloc(size, GFP_KERNEL);
867
868 if( beacon == NULL )
869 return -ENOMEM;
870
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700871#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700872 if(params->dtim_period || !old )
873 beacon->dtim_period = params->dtim_period;
874 else
875 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700876#else
877 if(dtim_period || !old )
878 beacon->dtim_period = dtim_period;
879 else
880 beacon->dtim_period = old->dtim_period;
881#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700882
883 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
884 beacon->tail = beacon->head + head_len;
885 beacon->head_len = head_len;
886 beacon->tail_len = tail_len;
887
888 if(params->head) {
889 memcpy (beacon->head,params->head,beacon->head_len);
890 }
891 else {
892 if(old)
893 memcpy (beacon->head,old->head,beacon->head_len);
894 }
895
896 if(params->tail) {
897 memcpy (beacon->tail,params->tail,beacon->tail_len);
898 }
899 else {
900 if(old)
901 memcpy (beacon->tail,old->tail,beacon->tail_len);
902 }
903
904 *ppBeacon = beacon;
905
906 kfree(old);
907
908 return 0;
909
910}
Jeff Johnson295189b2012-06-20 16:38:30 -0700911
912v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
913{
914 int left = length;
915 v_U8_t *ptr = pIes;
916 v_U8_t elem_id,elem_len;
917
918 while(left >= 2)
919 {
920 elem_id = ptr[0];
921 elem_len = ptr[1];
922 left -= 2;
923 if(elem_len > left)
924 {
925 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700926 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -0700927 eid,elem_len,left);
928 return NULL;
929 }
930 if (elem_id == eid)
931 {
932 return ptr;
933 }
934
935 left -= elem_len;
936 ptr += (elem_len + 2);
937 }
938 return NULL;
939}
940
Jeff Johnson295189b2012-06-20 16:38:30 -0700941/* Check if rate is 11g rate or not */
942static int wlan_hdd_rate_is_11g(u8 rate)
943{
944 u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 104}; /* actual rate * 2 */
945 u8 i;
946 for (i = 0; i < 8; i++)
947 {
948 if(rate == gRateArray[i])
949 return TRUE;
950 }
951 return FALSE;
952}
953
954/* Check for 11g rate and set proper 11g only mode */
955static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
956 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
957{
958 u8 i, num_rates = pIe[0];
959
960 pIe += 1;
961 for ( i = 0; i < num_rates; i++)
962 {
963 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
964 {
965 /* If rate set have 11g rate than change the mode to 11G */
966 *pSapHw_mode = eSAP_DOT11_MODE_11g;
967 if (pIe[i] & BASIC_RATE_MASK)
968 {
969 /* If we have 11g rate as basic rate, it means mode
970 is 11g only mode.
971 */
972 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
973 *pCheckRatesfor11g = FALSE;
974 }
975 }
976 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
977 {
978 *require_ht = TRUE;
979 }
980 }
981 return;
982}
983
984static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
985{
986 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
987 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
988 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
989 u8 checkRatesfor11g = TRUE;
990 u8 require_ht = FALSE;
991 u8 *pIe=NULL;
992
993 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
994
995 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
996 pBeacon->head_len, WLAN_EID_SUPP_RATES);
997 if (pIe != NULL)
998 {
999 pIe += 1;
1000 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1001 &pConfig->SapHw_mode);
1002 }
1003
1004 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1005 WLAN_EID_EXT_SUPP_RATES);
1006 if (pIe != NULL)
1007 {
1008
1009 pIe += 1;
1010 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1011 &pConfig->SapHw_mode);
1012 }
1013
1014 if( pConfig->channel > 14 )
1015 {
1016 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
1017 }
1018
1019 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1020 WLAN_EID_HT_CAPABILITY);
1021
1022 if(pIe)
1023 {
1024 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
1025 if(require_ht)
1026 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
1027 }
1028}
1029
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301030static int wlan_hdd_add_ie(hdd_adapter_t* pHostapdAdapter, v_U8_t *genie,
1031 v_U8_t *total_ielen, v_U8_t *oui, v_U8_t oui_size)
1032{
1033 v_U8_t ielen = 0;
1034 v_U8_t *pIe = NULL;
1035 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1036
1037 pIe = wlan_hdd_get_vendor_oui_ie_ptr(oui, oui_size,
1038 pBeacon->tail, pBeacon->tail_len);
1039
1040 if (pIe)
1041 {
1042 ielen = pIe[1] + 2;
1043 if ((*total_ielen + ielen) <= MAX_GENIE_LEN)
1044 {
1045 vos_mem_copy(&genie[*total_ielen], pIe, ielen);
1046 }
1047 else
1048 {
1049 hddLog( VOS_TRACE_LEVEL_ERROR, "**Ie Length is too big***");
1050 return -EINVAL;
1051 }
1052 *total_ielen += ielen;
1053 }
1054 return 0;
1055}
1056
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001057#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001058static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1059 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001060#else
1061static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1062 struct cfg80211_beacon_data *params)
1063#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001064{
1065 v_U8_t *genie;
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301066 v_U8_t total_ielen = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001067 v_U8_t addIE[1] = {0};
Jeff Johnsone7245742012-09-05 17:12:55 -07001068 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001069
1070 genie = vos_mem_malloc(MAX_GENIE_LEN);
1071
1072 if(genie == NULL) {
1073
1074 return -ENOMEM;
1075 }
1076
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301077 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1078 &total_ielen, WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001079 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301080 ret = -EINVAL;
1081 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001082 }
1083
1084#ifdef WLAN_FEATURE_WFD
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301085 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1086 &total_ielen, WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE))
1087 {
1088 ret = -EINVAL;
1089 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001090 }
1091#endif
1092
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301093 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1094 &total_ielen, P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001095 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301096 ret = -EINVAL;
1097 goto done;
1098 }
1099
1100 if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode)
1101 {
1102 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1103 &total_ielen, SS_OUI_TYPE, SS_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001104 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301105 ret = -EINVAL;
1106 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001107 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001108 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001109
1110 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1111 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1112 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1113 {
1114 hddLog(LOGE,
1115 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001116 ret = -EINVAL;
1117 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001118 }
1119
1120 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1121 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1122 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1123 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1124 ==eHAL_STATUS_FAILURE)
1125 {
1126 hddLog(LOGE,
1127 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001128 ret = -EINVAL;
1129 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001130 }
1131
1132 // Added for ProResp IE
1133 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1134 {
1135 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1136 u8 probe_rsp_ie_len[3] = {0};
1137 u8 counter = 0;
1138 /* Check Probe Resp Length if it is greater then 255 then Store
1139 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1140 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1141 Store More then 255 bytes into One Variable.
1142 */
1143 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1144 {
1145 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1146 {
1147 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1148 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1149 }
1150 else
1151 {
1152 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1153 rem_probe_resp_ie_len = 0;
1154 }
1155 }
1156
1157 rem_probe_resp_ie_len = 0;
1158
1159 if (probe_rsp_ie_len[0] > 0)
1160 {
1161 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1162 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1163 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1164 probe_rsp_ie_len[0], NULL,
1165 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1166 {
1167 hddLog(LOGE,
1168 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001169 ret = -EINVAL;
1170 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001171 }
1172 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1173 }
1174
1175 if (probe_rsp_ie_len[1] > 0)
1176 {
1177 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1178 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1179 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1180 probe_rsp_ie_len[1], NULL,
1181 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1182 {
1183 hddLog(LOGE,
1184 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001185 ret = -EINVAL;
1186 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001187 }
1188 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1189 }
1190
1191 if (probe_rsp_ie_len[2] > 0)
1192 {
1193 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1194 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1195 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1196 probe_rsp_ie_len[2], NULL,
1197 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1198 {
1199 hddLog(LOGE,
1200 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001201 ret = -EINVAL;
1202 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001203 }
1204 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1205 }
1206
1207 if (probe_rsp_ie_len[1] == 0 )
1208 {
1209 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1210 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1211 eANI_BOOLEAN_FALSE) )
1212 {
1213 hddLog(LOGE,
1214 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1215 }
1216 }
1217
1218 if (probe_rsp_ie_len[2] == 0 )
1219 {
1220 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1221 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1222 eANI_BOOLEAN_FALSE) )
1223 {
1224 hddLog(LOGE,
1225 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1226 }
1227 }
1228
1229 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1230 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1231 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1232 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1233 == eHAL_STATUS_FAILURE)
1234 {
1235 hddLog(LOGE,
1236 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001237 ret = -EINVAL;
1238 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001239 }
1240 }
1241 else
1242 {
1243 // Reset WNI_CFG_PROBE_RSP Flags
1244 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1245
1246 hddLog(VOS_TRACE_LEVEL_INFO,
1247 "%s: No Probe Response IE received in set beacon",
1248 __func__);
1249 }
1250
1251 // Added for AssocResp IE
1252 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1253 {
1254 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1255 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1256 params->assocresp_ies_len, NULL,
1257 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1258 {
1259 hddLog(LOGE,
1260 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001261 ret = -EINVAL;
1262 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001263 }
1264
1265 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1266 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1267 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1268 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1269 == eHAL_STATUS_FAILURE)
1270 {
1271 hddLog(LOGE,
1272 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001273 ret = -EINVAL;
1274 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001275 }
1276 }
1277 else
1278 {
1279 hddLog(VOS_TRACE_LEVEL_INFO,
1280 "%s: No Assoc Response IE received in set beacon",
1281 __func__);
1282
1283 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1284 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1285 eANI_BOOLEAN_FALSE) )
1286 {
1287 hddLog(LOGE,
1288 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1289 }
1290 }
1291
Jeff Johnsone7245742012-09-05 17:12:55 -07001292done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001293 vos_mem_free(genie);
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301294 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07001295}
Jeff Johnson295189b2012-06-20 16:38:30 -07001296
1297/*
1298 * FUNCTION: wlan_hdd_validate_operation_channel
1299 * called by wlan_hdd_cfg80211_start_bss() and
1300 * wlan_hdd_cfg80211_set_channel()
1301 * This function validates whether given channel is part of valid
1302 * channel list.
1303 */
1304static VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
1305{
1306
1307 v_U32_t num_ch = 0;
1308 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1309 u32 indx = 0;
1310 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301311 v_U8_t fValidChannel = FALSE, count = 0;
1312 hdd_config_t *hdd_pConfig_ini= (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07001313
1314 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1315
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301316 if ( hdd_pConfig_ini->sapAllowAllChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001317 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301318 /* Validate the channel */
1319 for (count = RF_CHAN_1 ; count <= RF_CHAN_165 ; count++)
Jeff Johnson295189b2012-06-20 16:38:30 -07001320 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301321 if ( channel == rfChannels[count].channelNum )
1322 {
1323 fValidChannel = TRUE;
1324 break;
1325 }
1326 }
1327 if (fValidChannel != TRUE)
1328 {
1329 hddLog(VOS_TRACE_LEVEL_ERROR,
1330 "%s: Invalid Channel [%d]", __func__, channel);
1331 return VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001332 }
1333 }
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301334 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001335 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301336 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1337 valid_ch, &num_ch))
1338 {
1339 hddLog(VOS_TRACE_LEVEL_ERROR,
1340 "%s: failed to get valid channel list", __func__);
1341 return VOS_STATUS_E_FAILURE;
1342 }
1343 for (indx = 0; indx < num_ch; indx++)
1344 {
1345 if (channel == valid_ch[indx])
1346 {
1347 break;
1348 }
1349 }
1350
1351 if (indx >= num_ch)
1352 {
1353 hddLog(VOS_TRACE_LEVEL_ERROR,
1354 "%s: Invalid Channel [%d]", __func__, channel);
1355 return VOS_STATUS_E_FAILURE;
1356 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001357 }
1358 return VOS_STATUS_SUCCESS;
1359
1360}
1361
Viral Modi3a32cc52013-02-08 11:14:52 -08001362/**
1363 * FUNCTION: wlan_hdd_cfg80211_set_channel
1364 * This function is used to set the channel number
1365 */
1366static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
1367 struct ieee80211_channel *chan,
1368 enum nl80211_channel_type channel_type
1369 )
1370{
1371 v_U32_t num_ch = 0;
Jeff Johnson4416a782013-03-25 14:17:50 -07001372 int channel = 0;
Viral Modi3a32cc52013-02-08 11:14:52 -08001373 hdd_adapter_t *pAdapter = NULL;
1374 int freq = chan->center_freq; /* freq is in MHZ */
1375
1376 ENTER();
1377
1378 if( NULL == dev )
1379 {
1380 hddLog(VOS_TRACE_LEVEL_ERROR,
1381 "%s: Called with dev = NULL.\n", __func__);
1382 return -ENODEV;
1383 }
1384 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1385
1386 hddLog(VOS_TRACE_LEVEL_INFO,
1387 "%s: device_mode = %d freq = %d \n",__func__,
1388 pAdapter->device_mode, chan->center_freq);
1389 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1390 {
1391 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1392 return -EAGAIN;
1393 }
1394
1395 /*
1396 * Do freq to chan conversion
1397 * TODO: for 11a
1398 */
1399
1400 channel = ieee80211_frequency_to_channel(freq);
1401
1402 /* Check freq range */
1403 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
1404 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
1405 {
1406 hddLog(VOS_TRACE_LEVEL_ERROR,
1407 "%s: Channel [%d] is outside valid range from %d to %d\n",
1408 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
1409 WNI_CFG_CURRENT_CHANNEL_STAMAX);
1410 return -EINVAL;
1411 }
1412
1413 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1414
Gopichand Nakkala6ab19562013-03-07 13:59:42 +05301415 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode) &&
1416 (WLAN_HDD_P2P_GO != pAdapter->device_mode))
Viral Modi3a32cc52013-02-08 11:14:52 -08001417 {
1418 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
1419 {
1420 hddLog(VOS_TRACE_LEVEL_ERROR,
1421 "%s: Invalid Channel [%d] \n", __func__, channel);
1422 return -EINVAL;
1423 }
1424 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1425 "%s: set channel to [%d] for device mode =%d",
1426 __func__, channel,pAdapter->device_mode);
1427 }
1428 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Viral Modi3a32cc52013-02-08 11:14:52 -08001429 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Viral Modi3a32cc52013-02-08 11:14:52 -08001430 )
1431 {
1432 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
1433 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
1434 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1435
1436 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
1437 {
1438 /* Link is up then return cant set channel*/
1439 hddLog( VOS_TRACE_LEVEL_ERROR,
1440 "%s: IBSS Associated, can't set the channel\n", __func__);
1441 return -EINVAL;
1442 }
1443
1444 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
1445 pHddStaCtx->conn_info.operationChannel = channel;
1446 pRoamProfile->ChannelInfo.ChannelList =
1447 &pHddStaCtx->conn_info.operationChannel;
1448 }
1449 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Viral Modi3a32cc52013-02-08 11:14:52 -08001450 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Viral Modi3a32cc52013-02-08 11:14:52 -08001451 )
1452 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301453 if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
1454 {
1455 if(VOS_STATUS_SUCCESS !=
1456 wlan_hdd_validate_operation_channel(pAdapter,channel))
1457 {
1458 hddLog(VOS_TRACE_LEVEL_ERROR,
1459 "%s: Invalid Channel [%d] \n", __func__, channel);
1460 return -EINVAL;
1461 }
1462 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1463 }
1464 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
Viral Modi3a32cc52013-02-08 11:14:52 -08001465 {
1466 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
1467
1468 /* If auto channel selection is configured as enable/ 1 then ignore
1469 channel set by supplicant
1470 */
1471 if ( cfg_param->apAutoChannelSelection )
1472 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301473 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel =
1474 AUTO_CHANNEL_SELECT;
Viral Modi3a32cc52013-02-08 11:14:52 -08001475 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1476 "%s: set channel to auto channel (0) for device mode =%d",
1477 __func__, pAdapter->device_mode);
1478 }
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301479 else
1480 {
1481 if(VOS_STATUS_SUCCESS !=
1482 wlan_hdd_validate_operation_channel(pAdapter,channel))
1483 {
1484 hddLog(VOS_TRACE_LEVEL_ERROR,
1485 "%s: Invalid Channel [%d] \n", __func__, channel);
1486 return -EINVAL;
1487 }
1488 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1489 }
Viral Modi3a32cc52013-02-08 11:14:52 -08001490 }
1491 }
1492 else
1493 {
1494 hddLog(VOS_TRACE_LEVEL_FATAL,
1495 "%s: Invalid device mode failed to set valid channel", __func__);
1496 return -EINVAL;
1497 }
1498 EXIT();
1499 return 0;
1500}
1501
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301502/*
1503 * FUNCTION: wlan_hdd_select_cbmode
1504 * called by wlan_hdd_cfg80211_start_bss() and
1505 * This function selects the cbmode based on primary channel
1506 */
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001507VOS_STATUS wlan_sap_select_cbmode(void *pAdapter,eSapPhyMode SapHw_mode, v_U8_t channel)
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301508{
1509 tSmeConfigParams smeConfig;
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001510 hdd_context_t *pHddCtx = ( hdd_context_t *) pAdapter;
1511 hdd_config_t *pConfigIni = ((hdd_context_t *)(pAdapter))->cfg_ini;
1512
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301513 if(
1514#ifdef WLAN_FEATURE_11AC
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001515 SapHw_mode != eSAP_DOT11_MODE_11ac &&
1516 SapHw_mode != eSAP_DOT11_MODE_11ac_ONLY &&
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301517#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001518 SapHw_mode != eSAP_DOT11_MODE_11n &&
1519 SapHw_mode != eSAP_DOT11_MODE_11n_ONLY
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301520 )
1521 {
1522 return VOS_STATUS_SUCCESS;
1523 }
1524
1525 if (!pConfigIni->nChannelBondingMode5GHz) {
1526 return VOS_STATUS_SUCCESS;
1527 }
1528
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001529 //channel = pSapConfig->channel;
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301530 vos_mem_zero(&smeConfig, sizeof (tSmeConfigParams));
1531
1532 sme_GetConfigParam(pHddCtx->hHal, &smeConfig);
1533
1534#ifdef WLAN_FEATURE_11AC
1535
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001536 if ( SapHw_mode == eSAP_DOT11_MODE_11ac ||
1537 SapHw_mode == eSAP_DOT11_MODE_11ac_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301538 {
1539 if ( channel== 36 || channel == 52 || channel == 100 ||
1540 channel == 116 || channel == 149 )
1541 {
1542 smeConfig.csrConfig.channelBondingMode5GHz =
1543 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW - 1;
1544 }
1545 else if ( channel == 40 || channel == 56 || channel == 104 ||
1546 channel == 120 || channel == 153 )
1547 {
1548 smeConfig.csrConfig.channelBondingMode5GHz =
1549 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW - 1;
1550 }
1551 else if ( channel == 44 || channel == 60 || channel == 108 ||
1552 channel == 124 || channel == 157 )
1553 {
1554 smeConfig.csrConfig.channelBondingMode5GHz =
1555 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH -1;
1556 }
1557 else if ( channel == 48 || channel == 64 || channel == 112 ||
1558 channel == 128 || channel == 161 )
1559 {
1560 smeConfig.csrConfig.channelBondingMode5GHz =
1561 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH - 1;
1562 }
Shailender Karmuchi84f11f02013-02-12 17:11:45 -08001563 else if ( channel == 165 )
1564 {
1565 smeConfig.csrConfig.channelBondingMode5GHz = 0;
1566 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301567 }
1568#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001569 if ( SapHw_mode == eSAP_DOT11_MODE_11n ||
1570 SapHw_mode == eSAP_DOT11_MODE_11n_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301571 {
1572 if ( channel== 40 || channel == 48 || channel == 56 ||
1573 channel == 64 || channel == 104 || channel == 112 ||
1574 channel == 120 || channel == 128 || channel == 136 ||
1575 channel == 144 || channel == 153 || channel == 161 )
1576 {
1577 smeConfig.csrConfig.channelBondingMode5GHz = 1;
1578 }
1579 else if ( channel== 36 || channel == 44 || channel == 52 ||
1580 channel == 60 || channel == 100 || channel == 108 ||
1581 channel == 116 || channel == 124 || channel == 132 ||
1582 channel == 140 || channel == 149 || channel == 157 )
1583 {
1584 smeConfig.csrConfig.channelBondingMode5GHz = 2;
1585 }
Shailender Karmuchi84f11f02013-02-12 17:11:45 -08001586 else if ( channel == 165 )
1587 {
1588 smeConfig.csrConfig.channelBondingMode5GHz = 0;
1589 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301590 }
1591 pr_info ("cbmode selected=%ld\n",smeConfig.csrConfig.channelBondingMode5GHz);
1592
1593 sme_UpdateConfig (pHddCtx->hHal,&smeConfig);
1594 return VOS_STATUS_SUCCESS;
1595}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001596
Jeff Johnson295189b2012-06-20 16:38:30 -07001597#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1598static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1599 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001600#else
1601static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1602 struct cfg80211_beacon_data *params,
1603 const u8 *ssid, size_t ssid_len,
1604 enum nl80211_hidden_ssid hidden_ssid)
1605#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001606{
1607 tsap_Config_t *pConfig;
1608 beacon_data_t *pBeacon = NULL;
1609 struct ieee80211_mgmt *pMgmt_frame;
1610 v_U8_t *pIe=NULL;
1611 v_U16_t capab_info;
1612 eCsrAuthType RSNAuthType;
1613 eCsrEncryptionType RSNEncryptType;
1614 eCsrEncryptionType mcRSNEncryptType;
1615 int status = VOS_STATUS_SUCCESS;
1616 tpWLAN_SAPEventCB pSapEventCallback;
1617 hdd_hostapd_state_t *pHostapdState;
1618 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1619 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301620 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001621 struct qc_mac_acl_entry *acl_entry = NULL;
1622 v_SINT_t i;
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001623 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001624
1625 ENTER();
1626
1627 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1628
1629 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1630
1631 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1632
1633 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1634
1635 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1636
1637 //channel is already set in the set_channel Call back
1638 //pConfig->channel = pCommitConfig->channel;
1639
1640 /*Protection parameter to enable or disable*/
1641 pConfig->protEnabled =
1642 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1643
1644 pConfig->dtim_period = pBeacon->dtim_period;
1645
1646 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1647 pConfig->dtim_period);
1648
1649
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001650 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001651 {
1652 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001653 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001654 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001655 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001656 tANI_BOOLEAN restartNeeded;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001657 pConfig->ieee80211d = 1;
1658 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1659 sme_setRegInfo(hHal, pConfig->countryCode);
1660 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
Jeff Johnson295189b2012-06-20 16:38:30 -07001661 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001662 else
1663 {
1664 pConfig->ieee80211d = 0;
1665 }
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301666 /*
1667 * If auto channel is configured i.e. channel is 0,
1668 * so skip channel validation.
1669 */
1670 if( AUTO_CHANNEL_SELECT != pConfig->channel )
1671 {
1672 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1673 {
1674 hddLog(VOS_TRACE_LEVEL_ERROR,
1675 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1676 return -EINVAL;
1677 }
1678 }
1679 else
1680 {
1681 if(1 != pHddCtx->is_dynamic_channel_range_set)
1682 {
1683 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
1684 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
1685 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
1686 }
1687 pHddCtx->is_dynamic_channel_range_set = 0;
1688 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001689 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001690 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001691 {
1692 pConfig->ieee80211d = 0;
1693 }
1694 pConfig->authType = eSAP_AUTO_SWITCH;
1695
1696 capab_info = pMgmt_frame->u.beacon.capab_info;
1697
1698 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
1699 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1700
1701 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1702
1703 /*Set wps station to configured*/
1704 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1705
1706 if(pIe)
1707 {
1708 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1709 {
1710 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1711 return -EINVAL;
1712 }
1713 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1714 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001715 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001716 /* Check 15 bit of WPS IE as it contain information for wps state
1717 * WPS state
1718 */
1719 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1720 {
1721 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1722 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1723 {
1724 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1725 }
1726 }
1727 }
1728 else
1729 {
1730 pConfig->wps_state = SAP_WPS_DISABLED;
1731 }
1732 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
1733
1734 pConfig->RSNWPAReqIELength = 0;
1735 pConfig->pRSNWPAReqIE = NULL;
1736 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1737 WLAN_EID_RSN);
1738 if(pIe && pIe[1])
1739 {
1740 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1741 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1742 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1743 /* The actual processing may eventually be more extensive than
1744 * this. Right now, just consume any PMKIDs that are sent in
1745 * by the app.
1746 * */
1747 status = hdd_softap_unpackIE(
1748 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1749 &RSNEncryptType,
1750 &mcRSNEncryptType,
1751 &RSNAuthType,
1752 pConfig->pRSNWPAReqIE[1]+2,
1753 pConfig->pRSNWPAReqIE );
1754
1755 if( VOS_STATUS_SUCCESS == status )
1756 {
1757 /* Now copy over all the security attributes you have
1758 * parsed out
1759 * */
1760 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1761 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1762 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1763 = RSNEncryptType;
1764 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1765 "EncryptionType = %d mcEncryptionType = %d\n"),
1766 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1767 }
1768 }
1769
1770 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1771 pBeacon->tail, pBeacon->tail_len);
1772
1773 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1774 {
1775 if (pConfig->pRSNWPAReqIE)
1776 {
1777 /*Mixed mode WPA/WPA2*/
1778 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1779 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1780 }
1781 else
1782 {
1783 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1784 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1785 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1786 status = hdd_softap_unpackIE(
1787 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1788 &RSNEncryptType,
1789 &mcRSNEncryptType,
1790 &RSNAuthType,
1791 pConfig->pRSNWPAReqIE[1]+2,
1792 pConfig->pRSNWPAReqIE );
1793
1794 if( VOS_STATUS_SUCCESS == status )
1795 {
1796 /* Now copy over all the security attributes you have
1797 * parsed out
1798 * */
1799 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1800 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1801 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1802 = RSNEncryptType;
1803 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1804 "EncryptionType = %d mcEncryptionType = %d\n"),
1805 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1806 }
1807 }
1808 }
1809
Jeff Johnson4416a782013-03-25 14:17:50 -07001810 if (pConfig->RSNWPAReqIELength > sizeof wpaRsnIEdata) {
1811 hddLog( VOS_TRACE_LEVEL_ERROR, "**RSNWPAReqIELength is too large***");
1812 return -EINVAL;
1813 }
1814
Jeff Johnson295189b2012-06-20 16:38:30 -07001815 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1816
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001817#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001818 if (params->ssid != NULL)
1819 {
1820 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1821 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1822 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1823 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1824 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001825#else
1826 if (ssid != NULL)
1827 {
1828 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1829 pConfig->SSIDinfo.ssid.length = ssid_len;
1830 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1831 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1832 }
1833#endif
1834
Jeff Johnson295189b2012-06-20 16:38:30 -07001835 vos_mem_copy(pConfig->self_macaddr.bytes,
1836 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1837
1838 /* default value */
1839 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1840 pConfig->num_accept_mac = 0;
1841 pConfig->num_deny_mac = 0;
1842
1843 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1844 pBeacon->tail, pBeacon->tail_len);
1845
1846 /* pIe for black list is following form:
1847 type : 1 byte
1848 length : 1 byte
1849 OUI : 4 bytes
1850 acl type : 1 byte
1851 no of mac addr in black list: 1 byte
1852 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1853 */
1854 if ((pIe != NULL) && (pIe[1] != 0))
1855 {
1856 pConfig->SapMacaddr_acl = pIe[6];
1857 pConfig->num_deny_mac = pIe[7];
1858 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1859 pIe[6], pIe[7]);
1860 if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
1861 pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
1862 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1863 for (i = 0; i < pConfig->num_deny_mac; i++)
1864 {
1865 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1866 acl_entry++;
1867 }
1868 }
1869 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1870 pBeacon->tail, pBeacon->tail_len);
1871
1872 /* pIe for white list is following form:
1873 type : 1 byte
1874 length : 1 byte
1875 OUI : 4 bytes
1876 acl type : 1 byte
1877 no of mac addr in white list: 1 byte
1878 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1879 */
1880 if ((pIe != NULL) && (pIe[1] != 0))
1881 {
1882 pConfig->SapMacaddr_acl = pIe[6];
1883 pConfig->num_accept_mac = pIe[7];
1884 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
1885 pIe[6], pIe[7]);
1886 if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
1887 pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
1888 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1889 for (i = 0; i < pConfig->num_accept_mac; i++)
1890 {
1891 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1892 acl_entry++;
1893 }
1894 }
1895 wlan_hdd_set_sapHwmode(pHostapdAdapter);
1896
Jeff Johnsone7245742012-09-05 17:12:55 -07001897#ifdef WLAN_FEATURE_11AC
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08001898 /* Overwrite the hostapd setting for HW mode only for 11ac.
1899 * This is valid only if mode is set to 11n in hostapd and either AUTO or 11ac in .ini .
1900 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode) */
1901 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
1902 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
1903 (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
1904 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1905 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07001906 {
1907 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
1908 }
1909#endif
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301910
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001911 if( AUTO_CHANNEL_SELECT != pConfig->channel)
1912 wlan_sap_select_cbmode((WLAN_HDD_GET_CTX(pHostapdAdapter)),pConfig->SapHw_mode,pConfig->channel);
Jeff Johnson295189b2012-06-20 16:38:30 -07001913 // ht_capab is not what the name conveys,this is used for protection bitmap
1914 pConfig->ht_capab =
1915 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
1916
1917 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
1918 {
1919 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
1920 return -EINVAL;
1921 }
1922
1923 //Uapsd Enabled Bit
1924 pConfig->UapsdEnable =
1925 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
1926 //Enable OBSS protection
1927 pConfig->obssProtEnabled =
1928 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
1929
1930 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
1931 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
1932 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
1933 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
1934 (int)pConfig->channel);
1935 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
1936 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
1937 pConfig->authType);
1938 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
1939 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
1940 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
1941 pConfig->protEnabled, pConfig->obssProtEnabled);
1942
1943 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
1944 {
1945 //Bss already started. just return.
1946 //TODO Probably it should update some beacon params.
1947 hddLog( LOGE, "Bss Already started...Ignore the request");
1948 EXIT();
1949 return 0;
1950 }
1951
1952 pConfig->persona = pHostapdAdapter->device_mode;
1953
1954 pSapEventCallback = hdd_hostapd_SAPEventCB;
1955 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
1956 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
1957 {
1958 hddLog(LOGE,FL("SAP Start Bss fail\n"));
1959 return -EINVAL;
1960 }
1961
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001962 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07001963 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
1964
1965 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1966
1967 if (!VOS_IS_STATUS_SUCCESS(status))
1968 {
1969 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1970 ("ERROR: HDD vos wait for single_event failed!!\n"));
1971 VOS_ASSERT(0);
1972 }
1973
1974 //Succesfully started Bss update the state bit.
1975 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
1976
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001977#ifdef WLAN_FEATURE_P2P_DEBUG
1978 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
1979 {
1980 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
1981 {
1982 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1983 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001984 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001985 }
1986 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
1987 {
1988 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1989 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001990 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001991 }
1992 }
1993#endif
1994
Jeff Johnson295189b2012-06-20 16:38:30 -07001995 pHostapdState->bCommit = TRUE;
1996 EXIT();
1997
1998 return 0;
1999}
2000
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002001#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002002static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
2003 struct net_device *dev,
2004 struct beacon_parameters *params)
2005{
2006 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2007 int status=VOS_STATUS_SUCCESS;
2008
2009 ENTER();
2010
2011 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
2012
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002013 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2014 {
2015 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2016 "%s:LOGP in Progress. Ignore!!!", __func__);
2017 return -EAGAIN;
2018 }
2019
Jeff Johnson295189b2012-06-20 16:38:30 -07002020 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002021 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002022 )
2023 {
2024 beacon_data_t *old,*new;
2025
2026 old = pAdapter->sessionCtx.ap.beacon;
2027
2028 if (old)
2029 return -EALREADY;
2030
2031 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2032
2033 if(status != VOS_STATUS_SUCCESS)
2034 {
2035 hddLog(VOS_TRACE_LEVEL_FATAL,
2036 "%s:Error!!! Allocating the new beacon\n",__func__);
2037 return -EINVAL;
2038 }
2039
2040 pAdapter->sessionCtx.ap.beacon = new;
2041
2042 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2043 }
2044
2045 EXIT();
2046 return status;
2047}
2048
2049static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
2050 struct net_device *dev,
2051 struct beacon_parameters *params)
2052{
2053 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2054 int status=VOS_STATUS_SUCCESS;
2055
2056 ENTER();
2057
2058 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2059 __func__,pAdapter->device_mode);
2060
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002061 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2062 {
2063 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2064 "%s:LOGP in Progress. Ignore!!!", __func__);
2065 return -EAGAIN;
2066 }
2067
Jeff Johnson295189b2012-06-20 16:38:30 -07002068 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002069 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002070 )
2071 {
2072 beacon_data_t *old,*new;
2073
2074 old = pAdapter->sessionCtx.ap.beacon;
2075
2076 if (!old)
2077 return -ENOENT;
2078
2079 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2080
2081 if(status != VOS_STATUS_SUCCESS) {
2082 hddLog(VOS_TRACE_LEVEL_FATAL,
2083 "%s: Error!!! Allocating the new beacon\n",__func__);
2084 return -EINVAL;
2085 }
2086
2087 pAdapter->sessionCtx.ap.beacon = new;
2088
2089 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2090 }
2091
2092 EXIT();
2093 return status;
2094}
2095
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002096#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
2097
2098#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002099static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
2100 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002101#else
2102static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
2103 struct net_device *dev)
2104#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002105{
2106 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07002107 hdd_context_t *pHddCtx = NULL;
2108 hdd_scaninfo_t *pScanInfo = NULL;
2109 hdd_adapter_t *staAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002110 VOS_STATUS status = 0;
2111
2112 ENTER();
2113
2114 if (NULL == pAdapter)
2115 {
2116 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002117 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002118 return -ENODEV;
2119 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002120
Jeff Johnson4416a782013-03-25 14:17:50 -07002121 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002122 if (NULL == pHddCtx)
2123 {
2124 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002125 "%s: HDD context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002126 return -ENODEV;
2127 }
Jeff Johnson4416a782013-03-25 14:17:50 -07002128 if (pHddCtx->isLogpInProgress)
2129 {
2130 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2131 "%s:LOGP in Progress. Ignore!!!", __func__);
2132 return -EAGAIN;
2133 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002134
2135 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
2136 if (NULL == staAdapter)
2137 {
2138 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
2139 if (NULL == staAdapter)
2140 {
2141 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002142 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002143 return -ENODEV;
2144 }
2145 }
2146
2147 pScanInfo = &pHddCtx->scan_info;
2148
Jeff Johnson4416a782013-03-25 14:17:50 -07002149 if (pHddCtx->isLogpInProgress)
Jeff Johnson295189b2012-06-20 16:38:30 -07002150 {
2151 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2152 return -EAGAIN;
2153 }
2154
2155 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2156
2157 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2158 __func__,pAdapter->device_mode);
2159
Jeff Johnsone7245742012-09-05 17:12:55 -07002160 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
2161 {
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002162 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Jeff Johnsone7245742012-09-05 17:12:55 -07002163 hdd_abort_mac_scan(staAdapter->pHddCtx);
2164 status = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002165 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07002166 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
2167 if (!status)
2168 {
2169 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson902c9832012-12-10 14:28:09 -08002170 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002171 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07002172 VOS_ASSERT(pScanInfo->mScanPending);
2173 return 0;
2174 }
2175 }
2176
Jeff Johnson295189b2012-06-20 16:38:30 -07002177 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002178 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002179 )
2180 {
2181 beacon_data_t *old;
2182
2183 old = pAdapter->sessionCtx.ap.beacon;
2184
2185 if (!old)
2186 return -ENOENT;
2187
Jeff Johnson295189b2012-06-20 16:38:30 -07002188 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002189
2190 mutex_lock(&pHddCtx->sap_lock);
2191 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2192 {
Jeff Johnson4416a782013-03-25 14:17:50 -07002193 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss(pHddCtx->pvosContext) ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07002194 {
2195 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2196
2197 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2198
2199 if (!VOS_IS_STATUS_SUCCESS(status))
2200 {
2201 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2202 ("ERROR: HDD vos wait for single_event failed!!\n"));
2203 VOS_ASSERT(0);
2204 }
2205 }
2206 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2207 }
2208 mutex_unlock(&pHddCtx->sap_lock);
2209
2210 if(status != VOS_STATUS_SUCCESS)
2211 {
2212 hddLog(VOS_TRACE_LEVEL_FATAL,
2213 "%s:Error!!! Stopping the BSS\n",__func__);
2214 return -EINVAL;
2215 }
2216
Jeff Johnson4416a782013-03-25 14:17:50 -07002217 if (ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002218 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
2219 ==eHAL_STATUS_FAILURE)
2220 {
2221 hddLog(LOGE,
2222 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
2223 }
2224
Jeff Johnson4416a782013-03-25 14:17:50 -07002225 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002226 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2227 eANI_BOOLEAN_FALSE) )
2228 {
2229 hddLog(LOGE,
2230 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
2231 }
2232
2233 // Reset WNI_CFG_PROBE_RSP Flags
2234 wlan_hdd_reset_prob_rspies(pAdapter);
2235
2236 pAdapter->sessionCtx.ap.beacon = NULL;
2237 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002238#ifdef WLAN_FEATURE_P2P_DEBUG
2239 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
2240 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
2241 {
2242 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
2243 "GO got removed");
2244 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
2245 }
2246#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002247 }
2248 EXIT();
2249 return status;
2250}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002251
2252#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2253
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302254static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2255 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002256 struct cfg80211_ap_settings *params)
2257{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302258 hdd_adapter_t *pAdapter;
2259 hdd_context_t *pHddCtx;
2260 int status = 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002261
2262 ENTER();
2263
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302264 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002265 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302266 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2267 "%s: Device is Null", __func__);
2268 return -ENODEV;
2269 }
2270
2271 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2272 if (NULL == pAdapter)
2273 {
2274 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2275 "%s: HDD adapter is Null", __func__);
2276 return -ENODEV;
2277 }
2278
2279 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2280 {
2281 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2282 "%s: HDD adapter magic is invalid", __func__);
2283 return -ENODEV;
2284 }
2285
2286 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2287 if (NULL == pHddCtx)
2288 {
2289 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2290 "%s: HDD context is Null", __func__);
2291 return -ENODEV;
2292 }
2293
2294 if (pHddCtx->isLogpInProgress)
2295 {
2296 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2297 "%s: LOGP in Progress. Ignore!!!", __func__);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002298 return -EAGAIN;
2299 }
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302300
2301 if (pHddCtx->isLoadUnloadInProgress)
2302 {
2303 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2304 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
2305 return -EAGAIN;
2306 }
2307
2308 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2309 __func__, pAdapter->device_mode);
2310
2311 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002312 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002313 )
2314 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302315 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002316
2317 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302318
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002319 if (old)
2320 return -EALREADY;
2321
2322 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2323
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302324 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002325 {
2326 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302327 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002328 return -EINVAL;
2329 }
2330 pAdapter->sessionCtx.ap.beacon = new;
Viral Modi3a32cc52013-02-08 11:14:52 -08002331#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2332 wlan_hdd_cfg80211_set_channel(wiphy, dev, params->channel, params->channel_type);
2333#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002334 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2335 params->ssid_len, params->hidden_ssid);
2336 }
2337
2338 EXIT();
2339 return status;
2340}
2341
2342
2343static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
2344 struct net_device *dev,
2345 struct cfg80211_beacon_data *params)
2346{
2347 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2348 int status=VOS_STATUS_SUCCESS;
2349
2350 ENTER();
2351
2352 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2353 __func__, pAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002354 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2355 {
2356 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2357 return -EAGAIN;
2358 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002359
2360 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002361 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002362 )
2363 {
2364 beacon_data_t *old,*new;
2365
2366 old = pAdapter->sessionCtx.ap.beacon;
2367
2368 if (!old)
2369 return -ENOENT;
2370
2371 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2372
2373 if(status != VOS_STATUS_SUCCESS) {
2374 hddLog(VOS_TRACE_LEVEL_FATAL,
2375 "%s: Error!!! Allocating the new beacon\n",__func__);
2376 return -EINVAL;
2377 }
2378
2379 pAdapter->sessionCtx.ap.beacon = new;
2380
2381 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2382 }
2383
2384 EXIT();
2385 return status;
2386}
2387
2388#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2389
Jeff Johnson295189b2012-06-20 16:38:30 -07002390
2391static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2392 struct net_device *dev,
2393 struct bss_parameters *params)
2394{
2395 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2396
2397 ENTER();
2398
2399 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2400 __func__,pAdapter->device_mode);
2401
2402 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002403 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002404 )
2405 {
2406 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2407 * want to update this parameter */
2408 if (-1 != params->ap_isolate)
2409 {
2410 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
2411 }
2412 }
2413
2414 EXIT();
2415 return 0;
2416}
2417
2418/*
2419 * FUNCTION: wlan_hdd_cfg80211_change_iface
2420 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2421 */
2422int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2423 struct net_device *ndev,
2424 enum nl80211_iftype type,
2425 u32 *flags,
2426 struct vif_params *params
2427 )
2428{
2429 struct wireless_dev *wdev;
2430 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2431 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002432 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002433 tCsrRoamProfile *pRoamProfile = NULL;
2434 eCsrRoamBssType LastBSSType;
2435 hdd_config_t *pConfig = pHddCtx->cfg_ini;
2436 eMib_dot11DesiredBssType connectedBssType;
2437 VOS_STATUS status;
2438
2439 ENTER();
2440
2441 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2442 {
2443 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2444 return -EAGAIN;
2445 }
2446
2447 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2448 __func__, pAdapter->device_mode);
2449
2450 wdev = ndev->ieee80211_ptr;
2451
2452#ifdef WLAN_BTAMP_FEATURE
2453 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2454 (NL80211_IFTYPE_ADHOC == type)||
2455 (NL80211_IFTYPE_AP == type)||
2456 (NL80211_IFTYPE_P2P_GO == type))
2457 {
2458 pHddCtx->isAmpAllowed = VOS_FALSE;
2459 // stop AMP traffic
2460 status = WLANBAP_StopAmp();
2461 if(VOS_STATUS_SUCCESS != status )
2462 {
2463 pHddCtx->isAmpAllowed = VOS_TRUE;
2464 hddLog(VOS_TRACE_LEVEL_FATAL,
2465 "%s: Failed to stop AMP", __func__);
2466 return -EINVAL;
2467 }
2468 }
2469#endif //WLAN_BTAMP_FEATURE
2470 /* Reset the current device mode bit mask*/
2471 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2472
2473 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07002474 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002475 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002476 )
2477 {
2478 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2479 pRoamProfile = &pWextState->roamProfile;
2480 LastBSSType = pRoamProfile->BSSType;
2481
2482 switch (type)
2483 {
2484 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002485 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002486 hddLog(VOS_TRACE_LEVEL_INFO,
2487 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2488 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002489#ifdef WLAN_FEATURE_11AC
2490 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2491 {
2492 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2493 }
2494#endif
2495 pRoamProfile->phyMode =
2496 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002497 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002498 //Check for sub-string p2p to confirm its a p2p interface
2499 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002500 {
2501 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2502 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2503 }
2504 else
2505 {
2506 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002507 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002508 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002509 break;
2510 case NL80211_IFTYPE_ADHOC:
2511 hddLog(VOS_TRACE_LEVEL_INFO,
2512 "%s: setting interface Type to ADHOC", __func__);
2513 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2514 pRoamProfile->phyMode =
2515 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
2516 wdev->iftype = type;
2517 break;
2518
2519 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002520 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002521 {
2522 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2523 "%s: setting interface Type to %s", __func__,
2524 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2525
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002526 //Cancel any remain on channel for GO mode
2527 if (NL80211_IFTYPE_P2P_GO == type)
2528 {
2529 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2530 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002531 if (NL80211_IFTYPE_AP == type)
2532 {
2533 /* As Loading WLAN Driver one interface being created for p2p device
2534 * address. This will take one HW STA and the max number of clients
2535 * that can connect to softAP will be reduced by one. so while changing
2536 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2537 * interface as it is not required in SoftAP mode.
2538 */
2539
2540 // Get P2P Adapter
2541 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2542
2543 if (pP2pAdapter)
2544 {
2545 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2546 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2547 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2548 }
2549 }
2550
Jeff Johnson295189b2012-06-20 16:38:30 -07002551 //De-init the adapter.
2552 hdd_stop_adapter( pHddCtx, pAdapter );
2553 hdd_deinit_adapter( pHddCtx, pAdapter );
2554 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
Jeff Johnson295189b2012-06-20 16:38:30 -07002555 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2556 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002557
2558 //Disable BMPS and IMPS if enabled
2559 //before starting Go
2560 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2561 {
2562 if(VOS_STATUS_E_FAILURE ==
2563 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2564 {
2565 //Fail to Exit BMPS
2566 VOS_ASSERT(0);
2567 }
2568 }
2569
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002570 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2571 (pConfig->apRandomBssidEnabled))
2572 {
2573 /* To meet Android requirements create a randomized
2574 MAC address of the form 02:1A:11:Fx:xx:xx */
2575 get_random_bytes(&ndev->dev_addr[3], 3);
2576 ndev->dev_addr[0] = 0x02;
2577 ndev->dev_addr[1] = 0x1A;
2578 ndev->dev_addr[2] = 0x11;
2579 ndev->dev_addr[3] |= 0xF0;
2580 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2581 VOS_MAC_ADDR_SIZE);
2582 pr_info("wlan: Generated HotSpot BSSID "
2583 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2584 ndev->dev_addr[0],
2585 ndev->dev_addr[1],
2586 ndev->dev_addr[2],
2587 ndev->dev_addr[3],
2588 ndev->dev_addr[4],
2589 ndev->dev_addr[5]);
2590 }
2591
Jeff Johnson295189b2012-06-20 16:38:30 -07002592 hdd_set_ap_ops( pAdapter->dev );
2593
2594 status = hdd_init_ap_mode(pAdapter);
2595 if(status != VOS_STATUS_SUCCESS)
2596 {
2597 hddLog(VOS_TRACE_LEVEL_FATAL,
2598 "%s: Error initializing the ap mode", __func__);
2599 return -EINVAL;
2600 }
2601 hdd_set_conparam(1);
2602
Jeff Johnson295189b2012-06-20 16:38:30 -07002603 /*interface type changed update in wiphy structure*/
2604 if(wdev)
2605 {
2606 wdev->iftype = type;
2607 pHddCtx->change_iface = type;
2608 }
2609 else
2610 {
2611 hddLog(VOS_TRACE_LEVEL_ERROR,
2612 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2613 return -EINVAL;
2614 }
2615 goto done;
2616 }
2617
2618 default:
2619 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2620 __func__);
2621 return -EOPNOTSUPP;
2622 }
2623 }
2624 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002625 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002626 )
2627 {
2628 switch(type)
2629 {
2630 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002631 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002632 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002633 hdd_stop_adapter( pHddCtx, pAdapter );
2634 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002635 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002636 //Check for sub-string p2p to confirm its a p2p interface
2637 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002638 {
2639 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2640 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2641 }
2642 else
2643 {
2644 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002645 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002646 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002647 hdd_set_conparam(0);
2648 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002649 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2650 hdd_set_station_ops( pAdapter->dev );
2651 status = hdd_init_station_mode( pAdapter );
2652 if( VOS_STATUS_SUCCESS != status )
2653 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002654 /* In case of JB, for P2P-GO, only change interface will be called,
2655 * This is the right place to enable back bmps_imps()
2656 */
2657 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002658 goto done;
2659 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002660 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002661 wdev->iftype = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002662 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2663 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07002664 goto done;
2665 default:
2666 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2667 __func__);
2668 return -EOPNOTSUPP;
2669
2670 }
2671
2672 }
2673 else
2674 {
2675 return -EOPNOTSUPP;
2676 }
2677
2678
2679 if(pRoamProfile)
2680 {
2681 if ( LastBSSType != pRoamProfile->BSSType )
2682 {
2683 /*interface type changed update in wiphy structure*/
2684 wdev->iftype = type;
2685
2686 /*the BSS mode changed, We need to issue disconnect
2687 if connected or in IBSS disconnect state*/
2688 if ( hdd_connGetConnectedBssType(
2689 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2690 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2691 {
2692 /*need to issue a disconnect to CSR.*/
2693 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2694 if( eHAL_STATUS_SUCCESS ==
2695 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2696 pAdapter->sessionId,
2697 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2698 {
2699 wait_for_completion_interruptible_timeout(
2700 &pAdapter->disconnect_comp_var,
2701 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2702 }
2703 }
2704 }
2705 }
2706
2707done:
2708 /*set bitmask based on updated value*/
2709 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
2710#ifdef WLAN_BTAMP_FEATURE
2711 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
2712 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2713 {
2714 //we are ok to do AMP
2715 pHddCtx->isAmpAllowed = VOS_TRUE;
2716 }
2717#endif //WLAN_BTAMP_FEATURE
2718 EXIT();
2719 return 0;
2720}
2721
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002722#ifdef FEATURE_WLAN_TDLS
2723static int wlan_hdd_tdls_add_station(struct wiphy *wiphy,
2724 struct net_device *dev, u8 *mac, bool update, tCsrStaParams *StaParams)
2725{
2726 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2727 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2728 VOS_STATUS status;
2729
2730 ENTER();
2731
2732 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
2733 {
2734 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2735 "Invalid arguments");
2736 return -EINVAL;
2737 }
Hoonki Lee27511902013-03-14 18:19:06 -07002738
2739 if ((eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) ||
2740 (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode))
2741 {
2742 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2743 "%s: TDLS mode is disabled OR not enabled in FW."
2744 MAC_ADDRESS_STR " Request declined.",
2745 __func__, MAC_ADDR_ARRAY(mac));
2746 return -ENOTSUPP;
2747 }
2748
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002749 if (pHddCtx->isLogpInProgress)
2750 {
2751 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2752 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07002753 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002754 return -EBUSY;
2755 }
2756
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002757 /* when self is on-going, we dont' want to change link_status */
2758 if ((0 == update) && wlan_hdd_tdls_is_peer_progress(pAdapter, mac))
2759 {
2760 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2761 "%s: " MAC_ADDRESS_STR
2762 " TDLS setup is ongoing. Request declined.",
2763 __func__, MAC_ADDR_ARRAY(mac));
2764 return -EPERM;
2765 }
2766
2767 /* when others are on-going, we want to change link_status to idle */
2768 if (wlan_hdd_tdls_is_progress(pAdapter, mac, TRUE))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002769 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002770 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2771 "%s: " MAC_ADDRESS_STR
2772 " TDLS setup is ongoing. Request declined.",
2773 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002774 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002775 }
2776
2777 /* first to check if we reached to maximum supported TDLS peer.
2778 TODO: for now, return -EPERM looks working fine,
2779 but need to check if any other errno fit into this category.*/
2780 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
2781 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002782 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2783 "%s: " MAC_ADDRESS_STR
2784 " TDLS Max peer already connected. Request declined.",
2785 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002786 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002787 }
2788 else
2789 {
2790 hddTdlsPeer_t *pTdlsPeer;
2791 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac);
2792 if (pTdlsPeer && (eTDLS_LINK_CONNECTED == pTdlsPeer->link_status))
2793 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002794 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2795 "%s: " MAC_ADDRESS_STR " already connected. Request declined.",
2796 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002797 return -EPERM;
2798 }
2799 }
2800
2801 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_CONNECTING);
2802
2803 INIT_COMPLETION(pAdapter->tdls_add_station_comp);
2804
2805 if (!update)
2806 {
2807 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
2808 pAdapter->sessionId, mac);
2809 }
2810 else
2811 {
2812 status = sme_ChangeTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
2813 pAdapter->sessionId, mac, StaParams);
2814 }
2815
2816 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_add_station_comp,
2817 msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
2818
2819 if (!status)
2820 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002821 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002822 "%s: timeout waiting for tdls add station indication",
2823 __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002824 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002825 }
2826 if ( eHAL_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus)
2827 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002828 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002829 "%s: Add Station is unsucessful", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002830 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002831 }
2832
2833 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07002834
2835error:
2836 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
2837 return -EPERM;
2838
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002839}
2840#endif
2841
Jeff Johnson295189b2012-06-20 16:38:30 -07002842static int wlan_hdd_change_station(struct wiphy *wiphy,
2843 struct net_device *dev,
2844 u8 *mac,
2845 struct station_parameters *params)
2846{
2847 VOS_STATUS status = VOS_STATUS_SUCCESS;
2848 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2849 v_MACADDR_t STAMacAddress;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002850#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002851 tCsrStaParams StaParams = {0};
2852 u32 set;
2853 tANI_U8 isBufSta = 0;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002854#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07002855 ENTER();
2856
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002857 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2858 {
2859 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2860 "%s:LOGP in Progress. Ignore!!!", __func__);
2861 return -EAGAIN;
2862 }
2863
Jeff Johnson295189b2012-06-20 16:38:30 -07002864 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
2865
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002866#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002867 StaParams.capability = params->capability;
2868 StaParams.uapsd_queues = params->uapsd_queues;
2869 StaParams.max_sp = params->max_sp;
2870
2871 if (0 != params->ext_capab_len)
2872 vos_mem_copy(StaParams.extn_capability, params->ext_capab,
2873 sizeof(StaParams.extn_capability));
2874
2875 if (NULL != params->ht_capa)
2876 vos_mem_copy(&StaParams.HTCap, params->ht_capa, sizeof(tSirHTCap));
2877
2878 StaParams.supported_rates_len = params->supported_rates_len;
2879
2880 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
2881 * The supported_rates array , for all the structures propogating till Add Sta
2882 * to the firmware has to be modified , if the supplicant (ieee80211) is
2883 * modified to send more rates.
2884 */
2885
2886 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
2887 */
2888 if (StaParams.supported_rates_len > SIR_MAC_MAX_SUPP_RATES)
2889 StaParams.supported_rates_len = SIR_MAC_MAX_SUPP_RATES;
2890
2891 if (0 != StaParams.supported_rates_len) {
2892 int i = 0;
2893 vos_mem_copy(StaParams.supported_rates, params->supported_rates,
2894 StaParams.supported_rates_len);
2895 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2896 "Supported Rates with Length %d", StaParams.supported_rates_len);
2897 for (i=0; i < StaParams.supported_rates_len; i++)
2898 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2899 "[%d]: %0x", i, StaParams.supported_rates[i]);
2900 }
2901
2902 if (NULL != params->vht_capa)
2903 vos_mem_copy(&StaParams.VHTCap, params->vht_capa, sizeof(tSirVHTCap));
2904
2905 set = params->sta_flags_set;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002906#endif
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002907
2908 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2909 || (pAdapter->device_mode == WLAN_HDD_P2P_GO))
Jeff Johnson295189b2012-06-20 16:38:30 -07002910 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002911 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
Jeff Johnson295189b2012-06-20 16:38:30 -07002912 {
2913 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
2914 WLANTL_STA_AUTHENTICATED);
2915
2916 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002917 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002918 return -EINVAL;
2919 }
2920 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002921#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002922 else if (pAdapter->device_mode == WLAN_HDD_INFRA_STATION ) {
2923 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
2924 if (0 != params->ext_capab_len ) {
2925 /*Define A Macro : TODO Sunil*/
2926 if ((1<<4) & StaParams.extn_capability[3]) {
2927 isBufSta = 1;
2928 }
2929 }
2930 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2931 "%s: TDLS Peer Parameters.", __func__);
2932 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2933 "uapsd_queues: %0x\n", params->uapsd_queues);
2934 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2935 "max_sp: %0x\n", params->max_sp);
2936 if (params->ht_capa) {
2937 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2938 "ht_capa->cap_info: %0x\n", params->ht_capa->cap_info);
2939 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2940 "ht_capa->ampdu_params_info: %0x\n",
2941 params->ht_capa->ampdu_params_info);
2942 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2943 "ht_capa->extended_capabilities: %0x\n",
2944 params->ht_capa->extended_ht_cap_info);
2945 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2946 "ht_capa->tx_BF_cap_info: %0x\n",
2947 params->ht_capa->tx_BF_cap_info);
2948 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2949 "ht_capa->antenna_selection_info: %0x\n",
2950 params->ht_capa->antenna_selection_info);
2951 }
2952 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2953 "params->capability: %0x\n",params->capability);
2954 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2955 "params->ext_capab_len: %0x\n",params->ext_capab_len);
2956 if (0 != params->ext_capab_len )
2957 {
2958 int i =0;
2959 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2960 "Extended capabilities:");
2961 for (i=0; i < params->ext_capab_len; i++)
2962 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2963 "[%d]: %0x", i, params->ext_capab[i]);
2964 }
2965 //status = wlan_hdd_tdls_set_peer_caps( mac, params->uapsd_queues,
2966 // params->max_sp, isBufSta);
2967 if (VOS_STATUS_SUCCESS != status) {
2968 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2969 "%s: wlan_hdd_tdls_set_peer_caps failed!", __func__);
2970 return -EINVAL;
2971 }
2972 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2973 "ht_capa->cap_info: %0x\n", StaParams.HTCap.capInfo);
2974 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 1, &StaParams);
2975
2976 if (VOS_STATUS_SUCCESS != status) {
2977 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2978 "%s: sme_ChangeTdlsPeerSta failed!", __func__);
2979 return -EINVAL;
2980 }
2981 }
2982 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002983#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002984
Jeff Johnsone7245742012-09-05 17:12:55 -07002985 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002986 return status;
2987}
2988
2989/*
2990 * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
2991 * This function is used to get peer station index in IBSS mode
2992 */
2993static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
2994{
2995 u8 idx = 0;
2996 u8 temp[VOS_MAC_ADDR_SIZE] = {0};
2997 ENTER();
2998 memset(temp, 0, VOS_MAC_ADDR_SIZE);
2999 for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
3000 {
3001 if ( (0 !=
3002 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
3003 && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
3004 temp, VOS_MAC_ADDR_SIZE)
3005 )
3006 {
3007 return idx;
3008 }
3009 }
3010 return idx;
3011}
3012
3013
3014/*
3015 * FUNCTION: wlan_hdd_cfg80211_add_key
3016 * This function is used to initialize the key information
3017 */
3018#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3019static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
3020 struct net_device *ndev,
3021 u8 key_index, bool pairwise,
3022 const u8 *mac_addr,
3023 struct key_params *params
3024 )
3025#else
3026static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
3027 struct net_device *ndev,
3028 u8 key_index, const u8 *mac_addr,
3029 struct key_params *params
3030 )
3031#endif
3032{
3033 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3034 tCsrRoamSetKey setKey;
3035 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3036 int status = 0;
3037 v_U32_t roamId= 0xFF;
3038 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
3039 hdd_hostapd_state_t *pHostapdState;
3040 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003041 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07003042
3043 ENTER();
3044
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003045 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3046 {
3047 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3048 "%s:LOGP in Progress. Ignore!!!", __func__);
3049 return -EAGAIN;
3050 }
3051
Jeff Johnson295189b2012-06-20 16:38:30 -07003052 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3053 __func__,pAdapter->device_mode);
3054
3055 if (CSR_MAX_NUM_KEY <= key_index)
3056 {
3057 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3058 key_index);
3059
3060 return -EINVAL;
3061 }
3062
3063 hddLog(VOS_TRACE_LEVEL_INFO,
3064 "%s: called with key index = %d & key length %d",
3065 __func__, key_index, params->key_len);
3066
3067 /*extract key idx, key len and key*/
3068 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3069 setKey.keyId = key_index;
3070 setKey.keyLength = params->key_len;
3071 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
3072
3073 switch (params->cipher)
3074 {
3075 case WLAN_CIPHER_SUITE_WEP40:
3076 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
3077 break;
3078
3079 case WLAN_CIPHER_SUITE_WEP104:
3080 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
3081 break;
3082
3083 case WLAN_CIPHER_SUITE_TKIP:
3084 {
3085 u8 *pKey = &setKey.Key[0];
3086 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
3087
3088 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
3089
3090 /*Supplicant sends the 32bytes key in this order
3091
3092 |--------------|----------|----------|
3093 | Tk1 |TX-MIC | RX Mic |
3094 |--------------|----------|----------|
3095 <---16bytes---><--8bytes--><--8bytes-->
3096
3097 */
3098 /*Sme expects the 32 bytes key to be in the below order
3099
3100 |--------------|----------|----------|
3101 | Tk1 |RX-MIC | TX Mic |
3102 |--------------|----------|----------|
3103 <---16bytes---><--8bytes--><--8bytes-->
3104 */
3105 /* Copy the Temporal Key 1 (TK1) */
3106 vos_mem_copy(pKey, params->key,16);
3107
3108 /*Copy the rx mic first*/
3109 vos_mem_copy(&pKey[16],&params->key[24],8);
3110
3111 /*Copy the tx mic */
3112 vos_mem_copy(&pKey[24],&params->key[16],8);
3113
3114
3115 break;
3116 }
3117
3118 case WLAN_CIPHER_SUITE_CCMP:
3119 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
3120 break;
3121
3122#ifdef FEATURE_WLAN_WAPI
3123 case WLAN_CIPHER_SUITE_SMS4:
3124 {
3125 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3126 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
3127 params->key, params->key_len);
3128 return 0;
3129 }
3130#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003131
Jeff Johnson295189b2012-06-20 16:38:30 -07003132#ifdef FEATURE_WLAN_CCX
3133 case WLAN_CIPHER_SUITE_KRK:
3134 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
3135 break;
3136#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003137
3138#ifdef WLAN_FEATURE_11W
3139 case WLAN_CIPHER_SUITE_AES_CMAC:
3140 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
3141 /* Temporarily we will ignore the setting of the IGTK. Once the Riva
3142 firmware is modified to handle the IGTK, then we will proceeed normally.
3143 For now, we just return success. */
3144 return 0;
3145 /* break; */
3146#endif
3147
Jeff Johnson295189b2012-06-20 16:38:30 -07003148 default:
3149 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
3150 __func__, params->cipher);
3151 return -EOPNOTSUPP;
3152 }
3153
3154 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
3155 __func__, setKey.encType);
3156
3157
3158
3159 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003160 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07003161 )
3162 {
3163
3164
3165 if (
3166#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3167 (!pairwise)
3168#else
3169 (!mac_addr || is_broadcast_ether_addr(mac_addr))
3170#endif
3171 )
3172 {
3173 /* set group key*/
3174 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson1250df42012-12-10 14:31:52 -08003175 "%s- %d: setting Broadcast key",
Jeff Johnson295189b2012-06-20 16:38:30 -07003176 __func__, __LINE__);
3177 setKey.keyDirection = eSIR_RX_ONLY;
3178 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3179 }
3180 else
3181 {
3182 /* set pairwise key*/
3183 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3184 "%s- %d: setting pairwise key",
3185 __func__, __LINE__);
3186 setKey.keyDirection = eSIR_TX_RX;
3187 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3188 }
3189
3190 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3191 if( pHostapdState->bssState == BSS_START )
3192 {
3193 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3194
3195 if ( status != eHAL_STATUS_SUCCESS )
3196 {
3197 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3198 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3199 __LINE__, status );
3200 }
3201 }
3202
3203 /* Saving WEP keys */
3204 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
3205 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
3206 {
3207 //Save the wep key in ap context. Issue setkey after the BSS is started.
3208 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3209 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
3210 }
3211 else
3212 {
3213 //Save the key in ap context. Issue setkey after the BSS is started.
3214 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3215 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
3216 }
3217 }
3218 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003219 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003220 )
3221 {
3222 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3223 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3224
3225 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
3226
Venkata Prathyusha Kuntupalliee2ce712013-01-17 14:09:24 -08003227 pWextState->roamProfile.Keys.defaultIndex = key_index;
3228
3229
Jeff Johnson295189b2012-06-20 16:38:30 -07003230 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
3231 params->key, params->key_len);
3232
3233 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3234
3235 if (!( ( IW_AUTH_KEY_MGMT_802_1X
3236 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
3237 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3238 )
3239 &&
3240 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3241 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3242 )
3243 )
3244 {
3245 /* in case of static WEP, macaddr/bssid is not coming from nl80211
3246 * interface, copy bssid for pairwise key and group macaddr for
3247 * group key initialization*/
3248
3249 tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
3250
3251 pWextState->roamProfile.negotiatedUCEncryptionType =
3252 pHddStaCtx->conn_info.ucEncryptionType =
3253 ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
3254 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
3255 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
3256
3257
3258 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3259 "%s: Negotiated encryption type %d", __func__,
3260 pWextState->roamProfile.negotiatedUCEncryptionType);
3261
3262 sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
3263 &pWextState->roamProfile, true);
3264 setKey.keyLength = 0;
3265 setKey.keyDirection = eSIR_TX_RX;
3266
3267#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3268 if (pairwise)
3269 {
3270#endif
3271 if (mac_addr)
3272 {
3273 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3274 }
3275 else
3276 {
3277 /* macaddr is NULL, set the peerMac to bssId in case of BSS,
3278 * and peerMacAddress in case of IBSS*/
3279 if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
3280 {
3281 u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
3282 if (HDD_MAX_NUM_IBSS_STA != staidx)
3283 {
3284 vos_mem_copy(setKey.peerMac,
3285 &pHddStaCtx->conn_info.peerMacAddress[staidx],
3286 WNI_CFG_BSSID_LEN);
3287
3288 }
3289 else
3290 {
3291 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
3292 __func__);
3293 return -EOPNOTSUPP;
3294 }
3295 }
3296 else
3297 {
3298 vos_mem_copy(setKey.peerMac,
3299 &pHddStaCtx->conn_info.bssId[0],
3300 WNI_CFG_BSSID_LEN);
3301 }
3302 }
3303#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3304 }
3305 else
3306 {
3307 /* set group key*/
3308 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3309 "%s- %d: setting Group key",
3310 __func__, __LINE__);
3311 setKey.keyDirection = eSIR_RX_ONLY;
3312 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3313 }
3314#endif
3315 }
3316 else if (
3317#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3318 (!pairwise)
3319#else
3320 (!mac_addr || is_broadcast_ether_addr(mac_addr))
3321#endif
3322 )
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 else
3332 {
3333 /* set pairwise key*/
3334 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3335 "%s- %d: setting pairwise key",
3336 __func__, __LINE__);
3337 setKey.keyDirection = eSIR_TX_RX;
3338 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3339 }
3340
3341 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3342 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3343 __func__, setKey.peerMac[0], setKey.peerMac[1],
3344 setKey.peerMac[2], setKey.peerMac[3],
3345 setKey.peerMac[4], setKey.peerMac[5],
3346 setKey.keyDirection);
3347
3348 vos_status = wlan_hdd_check_ula_done(pAdapter);
3349
3350 if ( vos_status != VOS_STATUS_SUCCESS )
3351 {
3352 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3353 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
3354 __LINE__, vos_status );
3355
3356 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3357
3358 return -EINVAL;
3359
3360 }
3361
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003362#ifdef WLAN_FEATURE_VOWIFI_11R
3363 /* The supplicant may attempt to set the PTK once pre-authentication is done.
3364 Save the key in the UMAC and include it in the ADD BSS request */
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003365 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303366 if( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_WAIT )
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003367 {
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303368 return -EINVAL;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003369 }
3370#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07003371
3372 /* issue set key request to SME*/
3373 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3374 pAdapter->sessionId, &setKey, &roamId );
3375
3376 if ( 0 != status )
3377 {
3378 hddLog(VOS_TRACE_LEVEL_ERROR,
3379 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3380 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3381 return -EINVAL;
3382 }
3383
3384
3385 /* in case of IBSS as there was no information available about WEP keys during
3386 * IBSS join, group key intialized with NULL key, so re-initialize group key
3387 * with correct value*/
3388 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
3389 !( ( IW_AUTH_KEY_MGMT_802_1X
3390 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
3391 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3392 )
3393 &&
3394 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3395 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3396 )
3397 )
3398 {
3399 setKey.keyDirection = eSIR_RX_ONLY;
3400 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3401
3402 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3403 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3404 __func__, setKey.peerMac[0], setKey.peerMac[1],
3405 setKey.peerMac[2], setKey.peerMac[3],
3406 setKey.peerMac[4], setKey.peerMac[5],
3407 setKey.keyDirection);
3408
3409 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3410 pAdapter->sessionId, &setKey, &roamId );
3411
3412 if ( 0 != status )
3413 {
3414 hddLog(VOS_TRACE_LEVEL_ERROR,
3415 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
3416 __func__, status);
3417 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3418 return -EINVAL;
3419 }
3420 }
3421 }
3422
3423 return 0;
3424}
3425
3426/*
3427 * FUNCTION: wlan_hdd_cfg80211_get_key
3428 * This function is used to get the key information
3429 */
3430#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3431static int wlan_hdd_cfg80211_get_key(
3432 struct wiphy *wiphy,
3433 struct net_device *ndev,
3434 u8 key_index, bool pairwise,
3435 const u8 *mac_addr, void *cookie,
3436 void (*callback)(void *cookie, struct key_params*)
3437 )
3438#else
3439static int wlan_hdd_cfg80211_get_key(
3440 struct wiphy *wiphy,
3441 struct net_device *ndev,
3442 u8 key_index, const u8 *mac_addr, void *cookie,
3443 void (*callback)(void *cookie, struct key_params*)
3444 )
3445#endif
3446{
3447 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3448 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3449 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
3450 struct key_params params;
3451
3452 ENTER();
3453
3454 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3455 __func__,pAdapter->device_mode);
3456
3457 memset(&params, 0, sizeof(params));
3458
3459 if (CSR_MAX_NUM_KEY <= key_index)
3460 {
3461 return -EINVAL;
3462 }
3463
3464 switch(pRoamProfile->EncryptionType.encryptionType[0])
3465 {
3466 case eCSR_ENCRYPT_TYPE_NONE:
3467 params.cipher = IW_AUTH_CIPHER_NONE;
3468 break;
3469
3470 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3471 case eCSR_ENCRYPT_TYPE_WEP40:
3472 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3473 break;
3474
3475 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3476 case eCSR_ENCRYPT_TYPE_WEP104:
3477 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3478 break;
3479
3480 case eCSR_ENCRYPT_TYPE_TKIP:
3481 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3482 break;
3483
3484 case eCSR_ENCRYPT_TYPE_AES:
3485 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3486 break;
3487
3488 default:
3489 params.cipher = IW_AUTH_CIPHER_NONE;
3490 break;
3491 }
3492
3493 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3494 params.seq_len = 0;
3495 params.seq = NULL;
3496 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3497 callback(cookie, &params);
3498 return 0;
3499}
3500
3501/*
3502 * FUNCTION: wlan_hdd_cfg80211_del_key
3503 * This function is used to delete the key information
3504 */
3505#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3506static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3507 struct net_device *ndev,
3508 u8 key_index,
3509 bool pairwise,
3510 const u8 *mac_addr
3511 )
3512#else
3513static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3514 struct net_device *ndev,
3515 u8 key_index,
3516 const u8 *mac_addr
3517 )
3518#endif
3519{
3520 int status = 0;
3521
3522 //This code needs to be revisited. There is sme_removeKey API, we should
3523 //plan to use that. After the change to use correct index in setkey,
3524 //it is observed that this is invalidating peer
3525 //key index whenever re-key is done. This is affecting data link.
3526 //It should be ok to ignore del_key.
3527#if 0
3528 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3529 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
3530 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3531 tCsrRoamSetKey setKey;
3532 v_U32_t roamId= 0xFF;
3533
3534 ENTER();
3535
3536 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3537 __func__,pAdapter->device_mode);
3538
3539 if (CSR_MAX_NUM_KEY <= key_index)
3540 {
3541 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3542 key_index);
3543
3544 return -EINVAL;
3545 }
3546
3547 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3548 setKey.keyId = key_index;
3549
3550 if (mac_addr)
3551 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3552 else
3553 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3554
3555 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3556
3557 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003558 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07003559 )
3560 {
3561
3562 hdd_hostapd_state_t *pHostapdState =
3563 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3564 if( pHostapdState->bssState == BSS_START)
3565 {
3566 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3567
3568 if ( status != eHAL_STATUS_SUCCESS )
3569 {
3570 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3571 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3572 __LINE__, status );
3573 }
3574 }
3575 }
3576 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003577 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003578 )
3579 {
3580 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3581
3582 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3583
3584 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3585 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
3586 __func__, setKey.peerMac[0], setKey.peerMac[1],
3587 setKey.peerMac[2], setKey.peerMac[3],
3588 setKey.peerMac[4], setKey.peerMac[5]);
3589 if(pAdapter->sessionCtx.station.conn_info.connState ==
3590 eConnectionState_Associated)
3591 {
3592 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3593 pAdapter->sessionId, &setKey, &roamId );
3594
3595 if ( 0 != status )
3596 {
3597 hddLog(VOS_TRACE_LEVEL_ERROR,
3598 "%s: sme_RoamSetKey failure, returned %d",
3599 __func__, status);
3600 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3601 return -EINVAL;
3602 }
3603 }
3604 }
3605#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003606 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003607 return status;
3608}
3609
3610/*
3611 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3612 * This function is used to set the default tx key index
3613 */
3614#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3615static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3616 struct net_device *ndev,
3617 u8 key_index,
3618 bool unicast, bool multicast)
3619#else
3620static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3621 struct net_device *ndev,
3622 u8 key_index)
3623#endif
3624{
3625 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3626 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3627 int status = 0;
3628 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3629
3630 ENTER();
3631
3632 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3633 __func__,pAdapter->device_mode, key_index);
3634
3635 if (CSR_MAX_NUM_KEY <= key_index)
3636 {
3637 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3638 key_index);
3639
3640 return -EINVAL;
3641 }
3642
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003643 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3644 {
3645 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3646 "%s:LOGP in Progress. Ignore!!!", __func__);
3647 return -EAGAIN;
3648 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003649
3650 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003651 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003652 )
3653 {
3654 if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
3655 (eCSR_ENCRYPT_TYPE_TKIP !=
3656 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3657 (eCSR_ENCRYPT_TYPE_AES !=
3658 pWextState->roamProfile.EncryptionType.encryptionType[0])
3659 )
3660 {
3661 /* if default key index is not same as previous one,
3662 * then update the default key index */
3663
3664 tCsrRoamSetKey setKey;
3665 v_U32_t roamId= 0xFF;
3666 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
3667
3668 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
3669 __func__, key_index);
3670
3671 Keys->defaultIndex = (u8)key_index;
3672 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3673 setKey.keyId = key_index;
3674 setKey.keyLength = Keys->KeyLength[key_index];
3675
3676 vos_mem_copy(&setKey.Key[0],
3677 &Keys->KeyMaterial[key_index][0],
3678 Keys->KeyLength[key_index]);
3679
3680 setKey.keyDirection = eSIR_TX_ONLY;
3681
3682 vos_mem_copy(setKey.peerMac,
3683 &pHddStaCtx->conn_info.bssId[0],
3684 WNI_CFG_BSSID_LEN);
3685
3686 setKey.encType =
3687 pWextState->roamProfile.EncryptionType.encryptionType[0];
3688
3689 /* issue set key request */
3690 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3691 pAdapter->sessionId, &setKey, &roamId );
3692
3693 if ( 0 != status )
3694 {
3695 hddLog(VOS_TRACE_LEVEL_ERROR,
3696 "%s: sme_RoamSetKey failed, returned %d", __func__,
3697 status);
3698 return -EINVAL;
3699 }
3700 }
3701 }
3702
3703 /* In SoftAp mode setting key direction for default mode */
3704 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3705 {
3706 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3707 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3708 (eCSR_ENCRYPT_TYPE_AES !=
3709 pWextState->roamProfile.EncryptionType.encryptionType[0])
3710 )
3711 {
3712 /* Saving key direction for default key index to TX default */
3713 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3714 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3715 }
3716 }
3717
3718 return status;
3719}
3720
Jeff Johnson295189b2012-06-20 16:38:30 -07003721/*
3722 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3723 * This function is used to inform the BSS details to nl80211 interface.
3724 */
3725static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3726 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3727{
3728 struct net_device *dev = pAdapter->dev;
3729 struct wireless_dev *wdev = dev->ieee80211_ptr;
3730 struct wiphy *wiphy = wdev->wiphy;
3731 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3732 int chan_no;
3733 int ie_length;
3734 const char *ie;
3735 unsigned int freq;
3736 struct ieee80211_channel *chan;
3737 int rssi = 0;
3738 struct cfg80211_bss *bss = NULL;
3739
3740 ENTER();
3741
3742 if( NULL == pBssDesc )
3743 {
3744 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3745 return bss;
3746 }
3747
3748 chan_no = pBssDesc->channelId;
3749 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3750 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3751
3752 if( NULL == ie )
3753 {
3754 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3755 return bss;
3756 }
3757
3758#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3759 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3760 {
3761 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3762 }
3763 else
3764 {
3765 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3766 }
3767#else
3768 freq = ieee80211_channel_to_frequency(chan_no);
3769#endif
3770
3771 chan = __ieee80211_get_channel(wiphy, freq);
3772
3773 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3774 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3775 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3776 if (bss == NULL)
3777 {
3778 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3779
3780 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3781 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3782 pBssDesc->capabilityInfo,
3783 pBssDesc->beaconInterval, ie, ie_length,
3784 rssi, GFP_KERNEL ));
3785}
3786 else
3787 {
3788 return bss;
3789 }
3790}
3791
3792
3793
3794/*
3795 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3796 * This function is used to inform the BSS details to nl80211 interface.
3797 */
3798struct cfg80211_bss*
3799wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3800 tSirBssDescription *bss_desc
3801 )
3802{
3803 /*
3804 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3805 already exists in bss data base of cfg80211 for that particular BSS ID.
3806 Using cfg80211_inform_bss_frame to update the bss entry instead of
3807 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3808 now there is no possibility to get the mgmt(probe response) frame from PE,
3809 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3810 cfg80211_inform_bss_frame.
3811 */
3812 struct net_device *dev = pAdapter->dev;
3813 struct wireless_dev *wdev = dev->ieee80211_ptr;
3814 struct wiphy *wiphy = wdev->wiphy;
3815 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003816#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3817 qcom_ie_age *qie_age = NULL;
3818 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3819#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003820 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003821#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003822 const char *ie =
3823 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3824 unsigned int freq;
3825 struct ieee80211_channel *chan;
3826 struct ieee80211_mgmt *mgmt =
3827 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3828 struct cfg80211_bss *bss_status = NULL;
3829 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3830 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003831#ifdef WLAN_OPEN_SOURCE
3832 struct timespec ts;
3833#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003834
3835 ENTER();
3836
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003837 if (!mgmt)
3838 return NULL;
3839
Jeff Johnson295189b2012-06-20 16:38:30 -07003840 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003841
3842#ifdef WLAN_OPEN_SOURCE
3843 /* Android does not want the timestamp from the frame.
3844 Instead it wants a monotonic increasing value */
3845 get_monotonic_boottime(&ts);
3846 mgmt->u.probe_resp.timestamp =
3847 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3848#else
3849 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003850 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3851 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003852
3853#endif
3854
Jeff Johnson295189b2012-06-20 16:38:30 -07003855 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3856 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003857
3858#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3859 /* GPS Requirement: need age ie per entry. Using vendor specific. */
3860 /* Assuming this is the last IE, copy at the end */
3861 ie_length -=sizeof(qcom_ie_age);
3862 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
3863 qie_age->element_id = QCOM_VENDOR_IE_ID;
3864 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
3865 qie_age->oui_1 = QCOM_OUI1;
3866 qie_age->oui_2 = QCOM_OUI2;
3867 qie_age->oui_3 = QCOM_OUI3;
3868 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
3869 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
3870#endif
3871
Jeff Johnson295189b2012-06-20 16:38:30 -07003872 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3873
3874 mgmt->frame_control |=
3875 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3876
3877#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3878 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3879 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3880 {
3881 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3882 }
3883 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3884 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3885
3886 {
3887 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3888 }
3889 else
3890 {
3891 kfree(mgmt);
3892 return NULL;
3893 }
3894#else
3895 freq = ieee80211_channel_to_frequency(chan_no);
3896#endif
3897 chan = __ieee80211_get_channel(wiphy, freq);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08003898 /*when the band is changed on the fly using the GUI, three things are done
3899 * 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)
3900 * as part of the scan abort, message willbe queued to PE and we proceed with flushing and changinh the band.
3901 * pe will stop the scanning further and report back the results what ever it had till now by calling the call back function.
3902 * if the time between update band and scandone call back is sufficent enough the band change reflects in SME, SME validates the channels
3903 * and discards the channels correponding to previous band and calls back with zero bss results.
3904 * 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
3905 * all the channels correponding to previous band.this is due to race condition.but those channels are invalid to the new band and so
3906 * this function __ieee80211_get_channel will return NULL.Each time we report scan result with this pointer null warning kernel trace is printed.
3907 * if the scan results contain large number of APs continuosly kernel warning trace is printed and it will lead to apps watch dog bark.
3908 * So drop the bss and continue to next bss.
3909 */
3910 if(chan == NULL)
3911 {
3912 hddLog(VOS_TRACE_LEVEL_INFO, "%s chan pointer is NULL", __func__);
3913 return NULL;
3914 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003915 /*To keep the rssi icon of the connected AP in the scan window
3916 *and the rssi icon of the wireless networks in sync
3917 * */
3918 if (( eConnectionState_Associated ==
3919 pAdapter->sessionCtx.station.conn_info.connState ) &&
3920 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3921 pAdapter->sessionCtx.station.conn_info.bssId,
3922 WNI_CFG_BSSID_LEN)))
3923 {
3924 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3925 rssi = (pAdapter->rssi * 100);
3926 }
3927 else
3928 {
3929 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3930 }
3931
3932 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3933 frame_len, rssi, GFP_KERNEL);
3934 kfree(mgmt);
3935 return bss_status;
3936}
3937
3938/*
3939 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3940 * This function is used to update the BSS data base of CFG8011
3941 */
3942struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3943 tCsrRoamInfo *pRoamInfo
3944 )
3945{
3946 tCsrRoamConnectedProfile roamProfile;
3947 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3948 struct cfg80211_bss *bss = NULL;
3949
3950 ENTER();
3951
3952 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
3953 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
3954
3955 if (NULL != roamProfile.pBssDesc)
3956 {
3957 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
3958 &roamProfile);
3959
3960 if (NULL == bss)
3961 {
3962 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
3963 __func__);
3964 }
3965
3966 sme_RoamFreeConnectProfile(hHal, &roamProfile);
3967 }
3968 else
3969 {
3970 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
3971 __func__);
3972 }
3973 return bss;
3974}
3975
3976/*
3977 * FUNCTION: wlan_hdd_cfg80211_update_bss
3978 */
3979static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
3980 hdd_adapter_t *pAdapter
3981 )
3982{
3983 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3984 tCsrScanResultInfo *pScanResult;
3985 eHalStatus status = 0;
3986 tScanResultHandle pResult;
3987 struct cfg80211_bss *bss_status = NULL;
3988
3989 ENTER();
3990
3991 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3992 {
3993 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3994 return -EAGAIN;
3995 }
3996
3997 /*
3998 * start getting scan results and populate cgf80211 BSS database
3999 */
4000 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
4001
4002 /* no scan results */
4003 if (NULL == pResult)
4004 {
4005 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
4006 return status;
4007 }
4008
4009 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
4010
4011 while (pScanResult)
4012 {
4013 /*
4014 * cfg80211_inform_bss() is not updating ie field of bss entry, if
4015 * entry already exists in bss data base of cfg80211 for that
4016 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
4017 * bss entry instead of cfg80211_inform_bss, But this call expects
4018 * mgmt packet as input. As of now there is no possibility to get
4019 * the mgmt(probe response) frame from PE, converting bss_desc to
4020 * ieee80211_mgmt(probe response) and passing to c
4021 * fg80211_inform_bss_frame.
4022 * */
4023
4024 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
4025 &pScanResult->BssDescriptor);
4026
4027
4028 if (NULL == bss_status)
4029 {
4030 hddLog(VOS_TRACE_LEVEL_INFO,
4031 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
4032 }
4033 else
4034 {
4035 cfg80211_put_bss(bss_status);
4036 }
4037
4038 pScanResult = sme_ScanResultGetNext(hHal, pResult);
4039 }
4040
4041 sme_ScanResultPurge(hHal, pResult);
4042
4043 return 0;
4044}
4045
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004046void
4047hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
4048{
4049 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004050 "%02X:%02X:%02X:%02X:%02X:%02X\n",
4051 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
4052 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004053} /****** end hddPrintMacAddr() ******/
4054
4055void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004056hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004057{
4058 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004059 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
4060 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
4061 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
4062 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004063} /****** end hddPrintPmkId() ******/
4064
4065//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
4066//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
4067
4068//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
4069//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
4070
4071#define dump_bssid(bssid) \
4072 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004073 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
4074 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
4075 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004076 }
4077
4078#define dump_pmkid(pMac, pmkid) \
4079 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004080 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
4081 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
4082 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004083 }
4084
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07004085#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004086/*
4087 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
4088 * This function is used to notify the supplicant of a new PMKSA candidate.
4089 */
4090int wlan_hdd_cfg80211_pmksa_candidate_notify(
4091 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
4092 int index, bool preauth )
4093{
Jeff Johnsone7245742012-09-05 17:12:55 -07004094#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004095 struct net_device *dev = pAdapter->dev;
4096
4097 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07004098 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004099
4100 if( NULL == pRoamInfo )
4101 {
4102 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
4103 return -EINVAL;
4104 }
4105
4106 dump_bssid(pRoamInfo->bssid);
4107 cfg80211_pmksa_candidate_notify(dev, index,
4108 pRoamInfo->bssid, preauth, GFP_KERNEL);
Jeff Johnsone7245742012-09-05 17:12:55 -07004109#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004110 return 0;
4111}
4112#endif //FEATURE_WLAN_LFR
4113
Jeff Johnson295189b2012-06-20 16:38:30 -07004114/*
4115 * FUNCTION: hdd_cfg80211_scan_done_callback
4116 * scanning callback function, called after finishing scan
4117 *
4118 */
4119static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
4120 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
4121{
4122 struct net_device *dev = (struct net_device *) pContext;
4123 //struct wireless_dev *wdev = dev->ieee80211_ptr;
4124 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004125 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4126 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004127 struct cfg80211_scan_request *req = NULL;
4128 int ret = 0;
4129
4130 ENTER();
4131
4132 hddLog(VOS_TRACE_LEVEL_INFO,
4133 "%s called with halHandle = %p, pContext = %p,"
4134 "scanID = %d, returned status = %d\n",
4135 __func__, halHandle, pContext, (int) scanId, (int) status);
4136
4137 //Block on scan req completion variable. Can't wait forever though.
4138 ret = wait_for_completion_interruptible_timeout(
4139 &pScanInfo->scan_req_completion_event,
4140 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
4141 if (!ret)
4142 {
4143 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004144 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004145 }
4146
4147 if(pScanInfo->mScanPending != VOS_TRUE)
4148 {
4149 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004150 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004151 }
4152
4153 /* Check the scanId */
4154 if (pScanInfo->scanId != scanId)
4155 {
4156 hddLog(VOS_TRACE_LEVEL_INFO,
4157 "%s called with mismatched scanId pScanInfo->scanId = %d "
4158 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
4159 (int) scanId);
4160 }
4161
Jeff Johnson295189b2012-06-20 16:38:30 -07004162 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
4163 pAdapter);
4164
4165 if (0 > ret)
4166 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
4167
4168
4169 /* If any client wait scan result through WEXT
4170 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004171 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07004172 {
4173 /* The other scan request waiting for current scan finish
4174 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004175 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004176 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004177 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004178 }
4179 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004180 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004181 {
4182 struct net_device *dev = pAdapter->dev;
4183 union iwreq_data wrqu;
4184 int we_event;
4185 char *msg;
4186
4187 memset(&wrqu, '\0', sizeof(wrqu));
4188 we_event = SIOCGIWSCAN;
4189 msg = NULL;
4190 wireless_send_event(dev, we_event, &wrqu, msg);
4191 }
4192 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004193 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004194
4195 /* Get the Scan Req */
4196 req = pAdapter->request;
4197
4198 if (!req)
4199 {
4200 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004201 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07004202 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004203 }
4204
4205 /*
4206 * setting up 0, just in case.
4207 */
4208 req->n_ssids = 0;
4209 req->n_channels = 0;
4210 req->ie = 0;
4211
Jeff Johnson295189b2012-06-20 16:38:30 -07004212 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004213 /* Scan is no longer pending */
4214 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004215
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07004216 /*
4217 * cfg80211_scan_done informing NL80211 about completion
4218 * of scanning
4219 */
4220 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004221 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004222
Jeff Johnsone7245742012-09-05 17:12:55 -07004223allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004224 /* release the wake lock at the end of the scan*/
4225 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004226
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004227 /* Acquire wakelock to handle the case where APP's tries to suspend
4228 * immediatly after the driver gets connect request(i.e after scan)
4229 * from supplicant, this result in app's is suspending and not able
4230 * to process the connect request to AP */
4231 hdd_allow_suspend_timeout(100);
4232
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004233#ifdef FEATURE_WLAN_TDLS
4234 wlan_hdd_tdls_scan_done_callback(pAdapter);
4235#endif
4236
Jeff Johnson295189b2012-06-20 16:38:30 -07004237 EXIT();
4238 return 0;
4239}
4240
4241/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004242 * FUNCTION: hdd_isScanAllowed
4243 * Go through each adapter and check if scan allowed
4244 *
4245 */
4246v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
4247{
4248 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4249 hdd_station_ctx_t *pHddStaCtx = NULL;
4250 hdd_adapter_t *pAdapter = NULL;
4251 VOS_STATUS status = 0;
4252 v_U8_t staId = 0;
4253 v_U8_t *staMac = NULL;
4254
4255 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4256
4257 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4258 {
4259 pAdapter = pAdapterNode->pAdapter;
4260
4261 if( pAdapter )
4262 {
4263 hddLog(VOS_TRACE_LEVEL_INFO,
4264 "%s: Adapter with device mode %d exists",
4265 __func__, pAdapter->device_mode);
4266 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4267 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4268 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
4269 {
4270 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4271 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
4272 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
4273 {
4274 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
4275 hddLog(VOS_TRACE_LEVEL_ERROR,
4276 "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the "
4277 "middle of WPS/EAPOL exchange.", __func__,
4278 staMac[0], staMac[1], staMac[2],
4279 staMac[3], staMac[4], staMac[5]);
4280 return VOS_FALSE;
4281 }
4282 }
4283 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
4284 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
4285 {
4286 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
4287 {
4288 if ((pAdapter->aStaInfo[staId].isUsed) &&
4289 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
4290 {
4291 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
4292
4293 hddLog(VOS_TRACE_LEVEL_ERROR,
4294 "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the "
4295 "middle of WPS/EAPOL exchange.", __func__,
4296 staMac[0], staMac[1], staMac[2],
4297 staMac[3], staMac[4], staMac[5]);
4298 return VOS_FALSE;
4299 }
4300 }
4301 }
4302 }
4303 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4304 pAdapterNode = pNext;
4305 }
4306 hddLog(VOS_TRACE_LEVEL_INFO,
4307 "%s: Scan allowed", __func__);
4308 return VOS_TRUE;
4309}
4310
4311/*
Jeff Johnson295189b2012-06-20 16:38:30 -07004312 * FUNCTION: wlan_hdd_cfg80211_scan
4313 * this scan respond to scan trigger and update cfg80211 scan database
4314 * later, scan dump command can be used to recieve scan results
4315 */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08004316int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
4317#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4318 struct net_device *dev,
4319#endif
4320 struct cfg80211_scan_request *request)
4321{
4322#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4323 struct net_device *dev = request->wdev->netdev;
4324#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004325 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4326 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4327 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4328 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
4329 tCsrScanRequest scanRequest;
4330 tANI_U8 *channelList = NULL, i;
4331 v_U32_t scanId = 0;
4332 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004333 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004334 v_U8_t* pP2pIe = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004335
4336 ENTER();
4337
4338 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4339 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004340
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004341 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004342 (eConnectionState_Connecting ==
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004343 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004344 {
4345 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004346 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
4347 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004348 return -EBUSY;
4349 }
4350
Jeff Johnson295189b2012-06-20 16:38:30 -07004351#ifdef WLAN_BTAMP_FEATURE
4352 //Scan not supported when AMP traffic is on.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004353 if (VOS_TRUE == WLANBAP_AmpSessionOn())
Jeff Johnson295189b2012-06-20 16:38:30 -07004354 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004355 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004356 "%s: No scanning when AMP is on", __func__);
4357 return -EOPNOTSUPP;
4358 }
4359#endif
4360 //Scan on any other interface is not supported.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004361 if (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07004362 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004363 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004364 "%s: Not scanning on device_mode = %d",
4365 __func__, pAdapter->device_mode);
4366 return -EOPNOTSUPP;
4367 }
4368
4369 if (TRUE == pScanInfo->mScanPending)
4370 {
4371 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004372 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07004373 }
4374
4375 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4376 {
4377 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4378 "%s:LOGP in Progress. Ignore!!!", __func__);
4379 return -EAGAIN;
4380 }
4381
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07004382 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
4383 {
4384 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4385 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
4386 return -EAGAIN;
4387 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004388 //Don't Allow Scan and return busy if Remain On
4389 //Channel and action frame is pending
4390 //Otherwise Cancel Remain On Channel and allow Scan
4391 //If no action frame pending
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004392 if (0 != wlan_hdd_check_remain_on_channel(pAdapter))
Jeff Johnson32d95a32012-09-10 13:15:23 -07004393 {
4394 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
4395 return -EBUSY;
4396 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004397#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004398 /* if tdls disagree scan right now, return immediately.
4399 tdls will schedule the scan when scan is allowed. (return SUCCESS)
4400 or will reject the scan if any TDLS is in progress. (return -EBUSY)
4401 */
4402 status = wlan_hdd_tdls_scan_callback (pAdapter,
4403 wiphy,
4404#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4405 dev,
Gopichand Nakkalac3c42b92013-03-20 19:42:34 -07004406#endif
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004407 request);
4408 if(status <= 0)
4409 {
4410 hddLog(VOS_TRACE_LEVEL_INFO, "%s: TDLS Pending %d", __func__, status);
4411 return status;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004412 }
4413#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07004414
Jeff Johnson295189b2012-06-20 16:38:30 -07004415 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
4416 {
4417 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08004418 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004419 return -EAGAIN;
4420 }
4421 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
4422 {
4423 hddLog(VOS_TRACE_LEVEL_WARN,
4424 "%s: MAX TM Level Scan not allowed", __func__);
4425 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4426 return -EBUSY;
4427 }
4428 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4429
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004430 /* Check if scan is allowed at this point of time.
4431 */
4432 if (!hdd_isScanAllowed(pHddCtx))
4433 {
4434 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
4435 return -EBUSY;
4436 }
4437
Jeff Johnson295189b2012-06-20 16:38:30 -07004438 vos_mem_zero( &scanRequest, sizeof(scanRequest));
4439
4440 if (NULL != request)
4441 {
4442 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
4443 (int)request->n_ssids);
4444
4445 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
4446 * Becasue of this, driver is assuming that this is not wildcard scan and so
4447 * is not aging out the scan results.
4448 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07004449 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07004450 {
4451 request->n_ssids = 0;
4452 }
4453
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004454 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07004455 {
4456 tCsrSSIDInfo *SsidInfo;
4457 int j;
4458 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
4459 /* Allocate num_ssid tCsrSSIDInfo structure */
4460 SsidInfo = scanRequest.SSIDs.SSIDList =
4461 ( tCsrSSIDInfo *)vos_mem_malloc(
4462 request->n_ssids*sizeof(tCsrSSIDInfo));
4463
4464 if(NULL == scanRequest.SSIDs.SSIDList)
4465 {
4466 hddLog(VOS_TRACE_LEVEL_ERROR,
4467 "memory alloc failed SSIDInfo buffer");
4468 return -ENOMEM;
4469 }
4470
4471 /* copy all the ssid's and their length */
4472 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
4473 {
4474 /* get the ssid length */
4475 SsidInfo->SSID.length = request->ssids[j].ssid_len;
4476 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
4477 SsidInfo->SSID.length);
4478 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
4479 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
4480 j, SsidInfo->SSID.ssId);
4481 }
4482 /* set the scan type to active */
4483 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4484 }
4485 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4486 {
4487 /* set the scan type to active */
4488 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4489 }
4490 else
4491 {
4492 /*Set the scan type to default type, in this case it is ACTIVE*/
4493 scanRequest.scanType = pScanInfo->scan_mode;
4494 }
4495 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
4496 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4497 }
4498 else
4499 {
4500 /* set the scan type to active */
4501 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4502 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4503
4504 /* set min and max channel time to zero */
4505 scanRequest.minChnTime = 0;
4506 scanRequest.maxChnTime = 0;
4507 }
4508
4509 /* set BSSType to default type */
4510 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4511
4512 /*TODO: scan the requested channels only*/
4513
4514 /*Right now scanning all the channels */
4515 if( request )
4516 {
4517 if( request->n_channels )
4518 {
4519 channelList = vos_mem_malloc( request->n_channels );
4520 if( NULL == channelList )
4521 {
4522 status = -ENOMEM;
4523 goto free_mem;
4524 }
4525
4526 for( i = 0 ; i < request->n_channels ; i++ )
4527 channelList[i] = request->channels[i]->hw_value;
4528 }
4529
4530 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4531 scanRequest.ChannelInfo.ChannelList = channelList;
4532
4533 /* set requestType to full scan */
4534 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004535
4536 /* Flush the scan results(only p2p beacons) for STA scan and P2P
4537 * search (Flush on both full scan and social scan but not on single
4538 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
4539 */
4540
4541 /* Supplicant does single channel scan after 8-way handshake
4542 * and in that case driver shoudnt flush scan results. If
4543 * driver flushes the scan results here and unfortunately if
4544 * the AP doesnt respond to our probe req then association
4545 * fails which is not desired
4546 */
4547
4548 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4549 {
4550 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4551 pAdapter->sessionId );
4552 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004553
4554 if( request->ie_len )
4555 {
4556 /* save this for future association (join requires this) */
4557 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4558 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4559 pScanInfo->scanAddIE.length = request->ie_len;
4560
4561 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004562 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4563 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004564 )
4565 {
4566 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4567 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4568 }
4569
4570 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4571 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4572
Jeff Johnson295189b2012-06-20 16:38:30 -07004573 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4574 request->ie_len);
4575 if (pP2pIe != NULL)
4576 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004577#ifdef WLAN_FEATURE_P2P_DEBUG
4578 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4579 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4580 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4581 {
4582 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4583 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4584 "Go nego completed to Connection is started");
4585 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4586 "for 8way Handshake");
4587 }
4588 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4589 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4590 {
4591 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4592 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4593 "Disconnected state to Connection is started");
4594 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4595 "for 4way Handshake");
4596 }
4597#endif
4598
Jeff Johnsone7245742012-09-05 17:12:55 -07004599 /* no_cck will be set during p2p find to disable 11b rates */
4600 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004601 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004602 hddLog(VOS_TRACE_LEVEL_INFO,
4603 "%s: This is a P2P Search", __func__);
4604 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004605
Jeff Johnsone7245742012-09-05 17:12:55 -07004606 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4607 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004608 /* set requestType to P2P Discovery */
4609 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004610 }
4611
4612 /*
4613 Skip Dfs Channel in case of P2P Search
4614 if it is set in ini file
4615 */
4616 if(cfg_param->skipDfsChnlInP2pSearch)
4617 {
4618 scanRequest.skipDfsChnlInP2pSearch = 1;
4619 }
4620 else
4621 {
4622 scanRequest.skipDfsChnlInP2pSearch = 0;
4623 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004624
Jeff Johnson295189b2012-06-20 16:38:30 -07004625 }
4626 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004627 }
4628 }
4629
4630 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4631
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004632 /* acquire the wakelock to avoid the apps suspend during the scan. To
4633 * address the following issues.
4634 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4635 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4636 * for long time, this result in apps running at full power for long time.
4637 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4638 * be stuck in full power because of resume BMPS
4639 */
4640 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004641
4642 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004643 pAdapter->sessionId, &scanRequest, &scanId,
4644 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004645
Jeff Johnson295189b2012-06-20 16:38:30 -07004646 if (eHAL_STATUS_SUCCESS != status)
4647 {
4648 hddLog(VOS_TRACE_LEVEL_ERROR,
4649 "%s: sme_ScanRequest returned error %d", __func__, status);
4650 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004651 if(eHAL_STATUS_RESOURCES == status)
4652 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004653 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 -07004654 status = -EBUSY;
4655 } else {
4656 status = -EIO;
4657 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004658 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004659 goto free_mem;
4660 }
4661
4662 pScanInfo->mScanPending = TRUE;
4663 pAdapter->request = request;
4664 pScanInfo->scanId = scanId;
4665
4666 complete(&pScanInfo->scan_req_completion_event);
4667
4668free_mem:
4669 if( scanRequest.SSIDs.SSIDList )
4670 {
4671 vos_mem_free(scanRequest.SSIDs.SSIDList);
4672 }
4673
4674 if( channelList )
4675 vos_mem_free( channelList );
4676
4677 EXIT();
4678
4679 return status;
4680}
4681
4682/*
4683 * FUNCTION: wlan_hdd_cfg80211_connect_start
4684 * This function is used to start the association process
4685 */
4686int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004687 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004688{
4689 int status = 0;
4690 hdd_wext_state_t *pWextState;
4691 v_U32_t roamId;
4692 tCsrRoamProfile *pRoamProfile;
4693 eMib_dot11DesiredBssType connectedBssType;
4694 eCsrAuthType RSNAuthType;
4695
4696 ENTER();
4697
4698 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4699
4700 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4701 {
4702 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4703 return -EINVAL;
4704 }
4705
4706 pRoamProfile = &pWextState->roamProfile;
4707
4708 if (pRoamProfile)
4709 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004710 int ret = 0;
4711 hdd_station_ctx_t *pHddStaCtx;
4712 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4713 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4714
4715 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4716 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4717 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004718 {
4719 /* Issue disconnect to CSR */
4720 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4721 if( eHAL_STATUS_SUCCESS ==
4722 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4723 pAdapter->sessionId,
4724 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4725 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004726 ret = wait_for_completion_interruptible_timeout(
4727 &pAdapter->disconnect_comp_var,
4728 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4729 if (0 == ret)
4730 {
4731 VOS_ASSERT(0);
4732 }
4733 }
4734 }
4735 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4736 {
4737 ret = wait_for_completion_interruptible_timeout(
4738 &pAdapter->disconnect_comp_var,
4739 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4740 if (0 == ret)
4741 {
4742 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004743 }
4744 }
4745
4746 if (HDD_WMM_USER_MODE_NO_QOS ==
4747 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4748 {
4749 /*QoS not enabled in cfg file*/
4750 pRoamProfile->uapsd_mask = 0;
4751 }
4752 else
4753 {
4754 /*QoS enabled, update uapsd mask from cfg file*/
4755 pRoamProfile->uapsd_mask =
4756 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4757 }
4758
4759 pRoamProfile->SSIDs.numOfSSIDs = 1;
4760 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4761 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
4762 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
4763 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4764 ssid, ssid_len);
4765
4766 if (bssid)
4767 {
4768 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4769 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4770 WNI_CFG_BSSID_LEN);
4771 /* Save BSSID in seperate variable as well, as RoamProfile
4772 BSSID is getting zeroed out in the association process. And in
4773 case of join failure we should send valid BSSID to supplicant
4774 */
4775 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4776 WNI_CFG_BSSID_LEN);
4777 }
4778
4779 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4780 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4781 {
4782 /*set gen ie*/
4783 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4784 /*set auth*/
4785 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4786 }
4787 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4788 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4789 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4790 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4791 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4792 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4793 )
4794 {
4795 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4796 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4797 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4798 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4799 eCSR_AUTH_TYPE_AUTOSWITCH;
4800 pWextState->roamProfile.AuthType.authType[0] =
4801 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4802 }
4803#ifdef FEATURE_WLAN_WAPI
4804 if (pAdapter->wapi_info.nWapiMode)
4805 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004806 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004807 switch (pAdapter->wapi_info.wapiAuthMode)
4808 {
4809 case WAPI_AUTH_MODE_PSK:
4810 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004811 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004812 pAdapter->wapi_info.wapiAuthMode);
4813 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4814 break;
4815 }
4816 case WAPI_AUTH_MODE_CERT:
4817 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004818 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004819 pAdapter->wapi_info.wapiAuthMode);
4820 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4821 break;
4822 }
4823 } // End of switch
4824 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4825 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4826 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004827 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004828 pRoamProfile->AuthType.numEntries = 1;
4829 pRoamProfile->EncryptionType.numEntries = 1;
4830 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4831 pRoamProfile->mcEncryptionType.numEntries = 1;
4832 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4833 }
4834 }
4835#endif /* FEATURE_WLAN_WAPI */
4836 pRoamProfile->csrPersona = pAdapter->device_mode;
4837
Jeff Johnson32d95a32012-09-10 13:15:23 -07004838 if( operatingChannel )
4839 {
4840 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4841 pRoamProfile->ChannelInfo.numOfChannels = 1;
4842 }
Chet Lanctot186b5732013-03-18 10:26:30 -07004843 else
4844 {
4845 pRoamProfile->ChannelInfo.ChannelList = NULL;
4846 pRoamProfile->ChannelInfo.numOfChannels = 0;
4847 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004848
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004849 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
4850 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
4851 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
4852 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004853 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
4854 */
4855 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4856 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
4857 eConnectionState_Connecting);
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004858
Jeff Johnson295189b2012-06-20 16:38:30 -07004859 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4860 pAdapter->sessionId, pRoamProfile, &roamId);
4861
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004862 if( (eHAL_STATUS_SUCCESS != status) &&
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304863 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
4864
4865 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004866 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
4867 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
4868 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304869 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004870 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304871 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004872
4873 pRoamProfile->ChannelInfo.ChannelList = NULL;
4874 pRoamProfile->ChannelInfo.numOfChannels = 0;
4875
Jeff Johnson295189b2012-06-20 16:38:30 -07004876 }
4877 else
4878 {
4879 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4880 return -EINVAL;
4881 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004882 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004883 return status;
4884}
4885
4886/*
4887 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4888 * This function is used to set the authentication type (OPEN/SHARED).
4889 *
4890 */
4891static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4892 enum nl80211_auth_type auth_type)
4893{
4894 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4895 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4896
4897 ENTER();
4898
4899 /*set authentication type*/
4900 switch (auth_type)
4901 {
4902 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4903 case NL80211_AUTHTYPE_AUTOMATIC:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07004904#ifdef WLAN_FEATURE_VOWIFI_11R
4905 case NL80211_AUTHTYPE_FT:
4906#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07004907 hddLog(VOS_TRACE_LEVEL_INFO,
4908 "%s: set authentication type to OPEN", __func__);
4909 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4910 break;
4911
4912 case NL80211_AUTHTYPE_SHARED_KEY:
4913 hddLog(VOS_TRACE_LEVEL_INFO,
4914 "%s: set authentication type to SHARED", __func__);
4915 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4916 break;
4917#ifdef FEATURE_WLAN_CCX
4918 case NL80211_AUTHTYPE_NETWORK_EAP:
4919 hddLog(VOS_TRACE_LEVEL_INFO,
4920 "%s: set authentication type to CCKM WPA", __func__);
4921 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4922 break;
4923#endif
4924
4925
4926 default:
4927 hddLog(VOS_TRACE_LEVEL_ERROR,
4928 "%s: Unsupported authentication type %d", __func__,
4929 auth_type);
4930 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4931 return -EINVAL;
4932 }
4933
4934 pWextState->roamProfile.AuthType.authType[0] =
4935 pHddStaCtx->conn_info.authType;
4936 return 0;
4937}
4938
4939/*
4940 * FUNCTION: wlan_hdd_set_akm_suite
4941 * This function is used to set the key mgmt type(PSK/8021x).
4942 *
4943 */
4944static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
4945 u32 key_mgmt
4946 )
4947{
4948 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4949 ENTER();
4950
4951 /*set key mgmt type*/
4952 switch(key_mgmt)
4953 {
4954 case WLAN_AKM_SUITE_PSK:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05304955#ifdef WLAN_FEATURE_VOWIFI_11R
4956 case WLAN_AKM_SUITE_FT_PSK:
4957#endif
4958 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
Jeff Johnson295189b2012-06-20 16:38:30 -07004959 __func__);
4960 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
4961 break;
4962
4963 case WLAN_AKM_SUITE_8021X:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05304964#ifdef WLAN_FEATURE_VOWIFI_11R
4965 case WLAN_AKM_SUITE_FT_8021X:
4966#endif
4967 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
Jeff Johnson295189b2012-06-20 16:38:30 -07004968 __func__);
4969 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
4970 break;
4971#ifdef FEATURE_WLAN_CCX
4972#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
4973#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
4974 case WLAN_AKM_SUITE_CCKM:
4975 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
4976 __func__);
4977 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
4978 break;
4979#endif
4980
4981 default:
4982 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
4983 __func__, key_mgmt);
4984 return -EINVAL;
4985
4986 }
4987 return 0;
4988}
4989
4990/*
4991 * FUNCTION: wlan_hdd_cfg80211_set_cipher
4992 * This function is used to set the encryption type
4993 * (NONE/WEP40/WEP104/TKIP/CCMP).
4994 */
4995static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
4996 u32 cipher,
4997 bool ucast
4998 )
4999{
5000 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5001 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5002 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5003
5004 ENTER();
5005
5006 if (!cipher)
5007 {
5008 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
5009 __func__, cipher);
5010 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5011 }
5012 else
5013 {
5014
5015 /*set encryption method*/
5016 switch (cipher)
5017 {
5018 case IW_AUTH_CIPHER_NONE:
5019 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5020 break;
5021
5022 case WLAN_CIPHER_SUITE_WEP40:
5023 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
5024 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
5025 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
5026 else
5027 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5028 break;
5029
5030 case WLAN_CIPHER_SUITE_WEP104:
5031 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
5032 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
5033 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
5034 else
5035 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
5036 break;
5037
5038 case WLAN_CIPHER_SUITE_TKIP:
5039 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5040 break;
5041
5042 case WLAN_CIPHER_SUITE_CCMP:
5043 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5044 break;
5045#ifdef FEATURE_WLAN_WAPI
5046 case WLAN_CIPHER_SUITE_SMS4:
5047 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
5048 break;
5049#endif
5050
5051#ifdef FEATURE_WLAN_CCX
5052 case WLAN_CIPHER_SUITE_KRK:
5053 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
5054 break;
5055#endif
5056 default:
5057 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
5058 __func__, cipher);
5059 return -EOPNOTSUPP;
5060 }
5061 }
5062
5063 if (ucast)
5064 {
5065 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
5066 __func__, encryptionType);
5067 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5068 pWextState->roamProfile.EncryptionType.numEntries = 1;
5069 pWextState->roamProfile.EncryptionType.encryptionType[0] =
5070 encryptionType;
5071 }
5072 else
5073 {
5074 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
5075 __func__, encryptionType);
5076 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
5077 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
5078 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
5079 }
5080
5081 return 0;
5082}
5083
5084
5085/*
5086 * FUNCTION: wlan_hdd_cfg80211_set_ie
5087 * This function is used to parse WPA/RSN IE's.
5088 */
5089int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
5090 u8 *ie,
5091 size_t ie_len
5092 )
5093{
5094 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5095 u8 *genie = ie;
5096 v_U16_t remLen = ie_len;
5097#ifdef FEATURE_WLAN_WAPI
5098 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
5099 u16 *tmp;
5100 v_U16_t akmsuiteCount;
5101 int *akmlist;
5102#endif
5103 ENTER();
5104
5105 /* clear previous assocAddIE */
5106 pWextState->assocAddIE.length = 0;
5107 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
5108
5109 while (remLen >= 2)
5110 {
5111 v_U16_t eLen = 0;
5112 v_U8_t elementId;
5113 elementId = *genie++;
5114 eLen = *genie++;
5115 remLen -= 2;
5116
5117 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
5118 __func__, elementId, eLen);
5119
5120 switch ( elementId )
5121 {
5122 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005123 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 -07005124 {
5125 hddLog(VOS_TRACE_LEVEL_ERROR,
5126 "%s: Invalid WPA IE", __func__);
5127 return -EINVAL;
5128 }
5129 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
5130 {
5131 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5132 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
5133 __func__, eLen + 2);
5134
5135 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5136 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005137 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
5138 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005139 VOS_ASSERT(0);
5140 return -ENOMEM;
5141 }
5142 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5143 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5144 pWextState->assocAddIE.length += eLen + 2;
5145
5146 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
5147 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5148 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5149 }
5150 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
5151 {
5152 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
5153 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5154 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
5155 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
5156 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
5157 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005158 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
5159 P2P_OUI_TYPE_SIZE))
5160 /*Consider P2P IE, only for P2P Client */
5161 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5162 {
5163 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5164 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
5165 __func__, eLen + 2);
5166
5167 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5168 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005169 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5170 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005171 VOS_ASSERT(0);
5172 return -ENOMEM;
5173 }
5174 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5175 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5176 pWextState->assocAddIE.length += eLen + 2;
5177
5178 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5179 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5180 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005181#ifdef WLAN_FEATURE_WFD
5182 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
5183 WFD_OUI_TYPE_SIZE))
5184 /*Consider WFD IE, only for P2P Client */
5185 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5186 {
5187 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5188 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
5189 __func__, eLen + 2);
5190
5191 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5192 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005193 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5194 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005195 VOS_ASSERT(0);
5196 return -ENOMEM;
5197 }
5198 // WFD IE is saved to Additional IE ; it should be accumulated to handle
5199 // WPS IE + P2P IE + WFD IE
5200 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5201 pWextState->assocAddIE.length += eLen + 2;
5202
5203 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5204 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5205 }
5206#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005207 /* Appending HS 2.0 Indication Element in Assiciation Request */
5208 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005209 HS20_OUI_TYPE_SIZE)) )
5210 {
5211 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5212 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
5213 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005214
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005215 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5216 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005217 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5218 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005219 VOS_ASSERT(0);
5220 return -ENOMEM;
5221 }
5222 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5223 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005224
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005225 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5226 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5227 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005228
Jeff Johnson295189b2012-06-20 16:38:30 -07005229 break;
5230 case DOT11F_EID_RSN:
5231 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
5232 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5233 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
5234 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
5235 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
5236 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005237 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
5238 case DOT11F_EID_EXTCAP:
5239 {
5240 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5241 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
5242 __func__, eLen + 2);
5243
5244 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5245 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005246 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5247 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005248 VOS_ASSERT(0);
5249 return -ENOMEM;
5250 }
5251 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5252 pWextState->assocAddIE.length += eLen + 2;
5253
5254 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5255 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5256 break;
5257 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005258#ifdef FEATURE_WLAN_WAPI
5259 case WLAN_EID_WAPI:
5260 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
5261 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
5262 pAdapter->wapi_info.nWapiMode);
5263 tmp = (u16 *)ie;
5264 tmp = tmp + 2; // Skip element Id and Len, Version
5265 akmsuiteCount = WPA_GET_LE16(tmp);
5266 tmp = tmp + 1;
5267 akmlist = (int *)(tmp);
5268 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
5269 {
5270 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
5271 }
5272 else
5273 {
5274 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
5275 VOS_ASSERT(0);
5276 return -EINVAL;
5277 }
5278
5279 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
5280 {
5281 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005282 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005283 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
5284 }
5285 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
5286 {
5287 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005288 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005289 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
5290 }
5291 break;
5292#endif
5293 default:
5294 hddLog (VOS_TRACE_LEVEL_ERROR,
5295 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005296 /* when Unknown IE is received we should break and continue
5297 * to the next IE in the buffer instead we were returning
5298 * so changing this to break */
5299 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005300 }
5301 genie += eLen;
5302 remLen -= eLen;
5303 }
5304 EXIT();
5305 return 0;
5306}
5307
5308/*
5309 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5310 * This function is used to initialize the security
5311 * parameters during connect operation.
5312 */
5313int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
5314 struct cfg80211_connect_params *req
5315 )
5316{
5317 int status = 0;
5318 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5319 ENTER();
5320
5321 /*set wpa version*/
5322 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5323
5324 if (req->crypto.wpa_versions)
5325 {
5326 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
5327 && ( (req->ie_len)
5328 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
5329 // Make sure that it is including a WPA IE.
5330 /* Currently NL is putting WPA version 1 even for open,
5331 * since p2p ie is also put in same buffer.
5332 * */
5333 {
5334 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5335 }
5336 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
5337 {
5338 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5339 }
5340 }
5341
5342 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
5343 pWextState->wpaVersion);
5344
5345 /*set authentication type*/
5346 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
5347
5348 if (0 > status)
5349 {
5350 hddLog(VOS_TRACE_LEVEL_ERROR,
5351 "%s: failed to set authentication type ", __func__);
5352 return status;
5353 }
5354
5355 /*set key mgmt type*/
5356 if (req->crypto.n_akm_suites)
5357 {
5358 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
5359 if (0 > status)
5360 {
5361 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
5362 __func__);
5363 return status;
5364 }
5365 }
5366
5367 /*set pairwise cipher type*/
5368 if (req->crypto.n_ciphers_pairwise)
5369 {
5370 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
5371 req->crypto.ciphers_pairwise[0], true);
5372 if (0 > status)
5373 {
5374 hddLog(VOS_TRACE_LEVEL_ERROR,
5375 "%s: failed to set unicast cipher type", __func__);
5376 return status;
5377 }
5378 }
5379 else
5380 {
5381 /*Reset previous cipher suite to none*/
5382 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
5383 if (0 > status)
5384 {
5385 hddLog(VOS_TRACE_LEVEL_ERROR,
5386 "%s: failed to set unicast cipher type", __func__);
5387 return status;
5388 }
5389 }
5390
5391 /*set group cipher type*/
5392 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
5393 false);
5394
5395 if (0 > status)
5396 {
5397 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
5398 __func__);
5399 return status;
5400 }
5401
Chet Lanctot186b5732013-03-18 10:26:30 -07005402#ifdef WLAN_FEATURE_11W
5403 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
5404#endif
5405
Jeff Johnson295189b2012-06-20 16:38:30 -07005406 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
5407 if (req->ie_len)
5408 {
5409 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
5410 if ( 0 > status)
5411 {
5412 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
5413 __func__);
5414 return status;
5415 }
5416 }
5417
5418 /*incase of WEP set default key information*/
5419 if (req->key && req->key_len)
5420 {
5421 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
5422 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
5423 )
5424 {
5425 if ( IW_AUTH_KEY_MGMT_802_1X
5426 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
5427 {
5428 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
5429 __func__);
5430 return -EOPNOTSUPP;
5431 }
5432 else
5433 {
5434 u8 key_len = req->key_len;
5435 u8 key_idx = req->key_idx;
5436
5437 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
5438 && (CSR_MAX_NUM_KEY > key_idx)
5439 )
5440 {
5441 hddLog(VOS_TRACE_LEVEL_INFO,
5442 "%s: setting default wep key, key_idx = %hu key_len %hu",
5443 __func__, key_idx, key_len);
5444 vos_mem_copy(
5445 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
5446 req->key, key_len);
5447 pWextState->roamProfile.Keys.KeyLength[key_idx] =
5448 (u8)key_len;
5449 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
5450 }
5451 }
5452 }
5453 }
5454
5455 return status;
5456}
5457
5458/*
5459 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5460 * This function is used to initialize the security
5461 * parameters during connect operation.
5462 */
5463static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
5464 struct net_device *ndev,
5465 struct cfg80211_connect_params *req
5466 )
5467{
5468 int status = 0;
5469 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
5470 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
5471 hdd_context_t *pHddCtx = NULL;
5472
5473 ENTER();
5474
5475 hddLog(VOS_TRACE_LEVEL_INFO,
5476 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5477
5478 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5479 {
5480 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5481 "%s:LOGP in Progress. Ignore!!!", __func__);
5482 return -EAGAIN;
5483 }
5484
5485#ifdef WLAN_BTAMP_FEATURE
5486 //Infra connect not supported when AMP traffic is on.
5487 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
5488 {
5489 hddLog(VOS_TRACE_LEVEL_ERROR,
5490 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005491 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07005492 }
5493#endif
5494 /*initialise security parameters*/
5495 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
5496
5497 if ( 0 > status)
5498 {
5499 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
5500 __func__);
5501 return status;
5502 }
5503
5504 //If Device Mode is Station Concurrent Sessions Exit BMps
Jeff Johnsona8a1a482012-12-12 16:49:33 -08005505 //P2P Mode will be taken care in Open/close adapter
Jeff Johnson295189b2012-06-20 16:38:30 -07005506 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
5507 (vos_concurrent_sessions_running()))
5508 {
5509 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5510
5511 if (NULL != pVosContext)
5512 {
5513 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5514 if(NULL != pHddCtx)
5515 {
5516 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
5517 }
5518 }
5519 }
5520
Mohit Khanna765234a2012-09-11 15:08:35 -07005521 if ( req->channel )
5522 {
5523 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5524 req->ssid_len, req->bssid,
5525 req->channel->hw_value);
5526 }
5527 else
5528 {
5529 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5530 req->ssid_len, req->bssid,
5531 0);
5532 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005533
5534 if (0 > status)
5535 {
5536 //ReEnable BMPS if disabled
5537 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5538 (NULL != pHddCtx))
5539 {
5540 //ReEnable Bmps and Imps back
5541 hdd_enable_bmps_imps(pHddCtx);
5542 }
5543
5544 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5545 return status;
5546 }
5547 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
5548 EXIT();
5549 return status;
5550}
5551
5552
5553/*
5554 * FUNCTION: wlan_hdd_cfg80211_disconnect
5555 * This function is used to issue a disconnect request to SME
5556 */
5557static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
5558 struct net_device *dev,
5559 u16 reason
5560 )
5561{
5562 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5563 tCsrRoamProfile *pRoamProfile =
5564 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
5565 int status = 0;
5566 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005567#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005568 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005569 tANI_U8 staIdx;
5570#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005571
5572 ENTER();
5573
5574 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
5575 __func__,pAdapter->device_mode);
5576
5577 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5578 __func__, reason);
5579
5580 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
5581 {
5582 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5583 "%s:LOGP in Progress. Ignore!!!",__func__);
5584 return -EAGAIN;
5585 }
5586 if (NULL != pRoamProfile)
5587 {
5588 /*issue disconnect request to SME, if station is in connected state*/
5589 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
5590 {
5591 eCsrRoamDisconnectReason reasonCode =
5592 eCSR_DISCONNECT_REASON_UNSPECIFIED;
5593 switch(reason)
5594 {
5595 case WLAN_REASON_MIC_FAILURE:
5596 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
5597 break;
5598
5599 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
5600 case WLAN_REASON_DISASSOC_AP_BUSY:
5601 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
5602 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
5603 break;
5604
5605 case WLAN_REASON_PREV_AUTH_NOT_VALID:
5606 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
5607 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
5608 break;
5609
5610 case WLAN_REASON_DEAUTH_LEAVING:
5611 default:
5612 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
5613 break;
5614 }
5615 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5616 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
5617 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5618
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005619#ifdef FEATURE_WLAN_TDLS
5620 /* First clean up the tdls peers if any */
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005621 for (staIdx = 0 ; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005622 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005623 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId == pAdapter->sessionId) &&
5624 (pHddCtx->tdlsConnInfo[staIdx].staId))
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005625 {
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005626 uint8 *mac;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005627 mac = pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005628 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07005629 "%s: call sme_DeleteTdlsPeerSta staId %d sessionId %d " MAC_ADDRESS_STR,
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005630 __func__, pHddCtx->tdlsConnInfo[staIdx].staId, pAdapter->sessionId,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07005631 MAC_ADDR_ARRAY(mac));
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005632 sme_DeleteTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005633 pAdapter->sessionId,
5634 mac);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005635 }
5636 }
5637#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005638 /*issue disconnect*/
5639 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5640 pAdapter->sessionId, reasonCode);
5641
5642 if ( 0 != status)
5643 {
5644 hddLog(VOS_TRACE_LEVEL_ERROR,
5645 "%s csrRoamDisconnect failure, returned %d \n",
5646 __func__, (int)status );
5647 return -EINVAL;
5648 }
5649
5650 wait_for_completion_interruptible_timeout(
5651 &pAdapter->disconnect_comp_var,
5652 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5653
5654
5655 /*stop tx queues*/
5656 netif_tx_disable(dev);
5657 netif_carrier_off(dev);
5658 }
5659 }
5660 else
5661 {
5662 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
5663 }
5664
5665 return status;
5666}
5667
5668/*
5669 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
5670 * This function is used to initialize the security
5671 * settings in IBSS mode.
5672 */
5673static int wlan_hdd_cfg80211_set_privacy_ibss(
5674 hdd_adapter_t *pAdapter,
5675 struct cfg80211_ibss_params *params
5676 )
5677{
5678 int status = 0;
5679 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5680 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5681 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5682
5683 ENTER();
5684
5685 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5686
5687 if (params->ie_len && ( NULL != params->ie) )
5688 {
5689 if (WLAN_EID_RSN == params->ie[0])
5690 {
5691 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5692 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5693 }
5694 else
5695 {
5696 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5697 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5698 }
5699 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
5700
5701 if (0 > status)
5702 {
5703 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
5704 __func__);
5705 return status;
5706 }
5707 }
5708
5709 pWextState->roamProfile.AuthType.authType[0] =
5710 pHddStaCtx->conn_info.authType =
5711 eCSR_AUTH_TYPE_OPEN_SYSTEM;
5712
5713 if (params->privacy)
5714 {
5715 /* Security enabled IBSS, At this time there is no information available
5716 * about the security paramters, so initialise the encryption type to
5717 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
5718 * The correct security parameters will be updated later in
5719 * wlan_hdd_cfg80211_add_key */
5720 /* Hal expects encryption type to be set inorder
5721 *enable privacy bit in beacons */
5722
5723 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5724 }
5725
5726 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5727 pWextState->roamProfile.EncryptionType.numEntries = 1;
5728 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
5729
5730 return status;
5731}
5732
5733/*
5734 * FUNCTION: wlan_hdd_cfg80211_join_ibss
5735 * This function is used to create/join an IBSS
5736 */
5737static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
5738 struct net_device *dev,
5739 struct cfg80211_ibss_params *params
5740 )
5741{
5742 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5743 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5744 tCsrRoamProfile *pRoamProfile;
5745 int status;
5746 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5747
5748 ENTER();
5749
5750 hddLog(VOS_TRACE_LEVEL_INFO,
5751 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5752
5753 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5754 {
5755 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5756 "%s:LOGP in Progress. Ignore!!!", __func__);
5757 return -EAGAIN;
5758 }
5759
5760 if (NULL == pWextState)
5761 {
5762 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5763 __func__);
5764 return -EIO;
5765 }
5766
5767 pRoamProfile = &pWextState->roamProfile;
5768
5769 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
5770 {
5771 hddLog (VOS_TRACE_LEVEL_ERROR,
5772 "%s Interface type is not set to IBSS \n", __func__);
5773 return -EINVAL;
5774 }
5775
5776 /* Set Channel */
5777 if (NULL != params->channel)
5778 {
5779 u8 channelNum;
5780 if (IEEE80211_BAND_5GHZ == params->channel->band)
5781 {
5782 hddLog(VOS_TRACE_LEVEL_ERROR,
5783 "%s: IBSS join is called with unsupported band %d",
5784 __func__, params->channel->band);
5785 return -EOPNOTSUPP;
5786 }
5787
5788 /* Get channel number */
5789 channelNum =
5790 ieee80211_frequency_to_channel(params->channel->center_freq);
5791
5792 /*TODO: use macro*/
5793 if (14 >= channelNum)
5794 {
5795 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5796 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5797 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5798 int indx;
5799
5800 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5801 validChan, &numChans))
5802 {
5803 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
5804 __func__);
5805 return -EOPNOTSUPP;
5806 }
5807
5808 for (indx = 0; indx < numChans; indx++)
5809 {
5810 if (channelNum == validChan[indx])
5811 {
5812 break;
5813 }
5814 }
5815 if (indx >= numChans)
5816 {
5817 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
5818 __func__, channelNum);
5819 return -EINVAL;
5820 }
5821 /* Set the Operational Channel */
5822 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
5823 channelNum);
5824 pRoamProfile->ChannelInfo.numOfChannels = 1;
5825 pHddStaCtx->conn_info.operationChannel = channelNum;
5826 pRoamProfile->ChannelInfo.ChannelList =
5827 &pHddStaCtx->conn_info.operationChannel;
5828 }
5829 else
5830 {
5831 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5832 __func__, channelNum);
5833 return -EINVAL;
5834 }
5835 }
5836
5837 /* Initialize security parameters */
5838 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5839 if (status < 0)
5840 {
5841 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5842 __func__);
5843 return status;
5844 }
5845
5846 /* Issue connect start */
5847 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005848 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005849
5850 if (0 > status)
5851 {
5852 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5853 return status;
5854 }
5855
5856 return 0;
5857}
5858
5859/*
5860 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5861 * This function is used to leave an IBSS
5862 */
5863static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5864 struct net_device *dev
5865 )
5866{
5867 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5868 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5869 tCsrRoamProfile *pRoamProfile;
5870
5871 ENTER();
5872
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005873 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5874 {
5875 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5876 "%s:LOGP in Progress. Ignore!!!", __func__);
5877 return -EAGAIN;
5878 }
5879
Jeff Johnson295189b2012-06-20 16:38:30 -07005880 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5881 if (NULL == pWextState)
5882 {
5883 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5884 __func__);
5885 return -EIO;
5886 }
5887
5888 pRoamProfile = &pWextState->roamProfile;
5889
5890 /* Issue disconnect only if interface type is set to IBSS */
5891 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5892 {
5893 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5894 __func__);
5895 return -EINVAL;
5896 }
5897
5898 /* Issue Disconnect request */
5899 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5900 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5901 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5902
5903 return 0;
5904}
5905
5906/*
5907 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5908 * This function is used to set the phy parameters
5909 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5910 */
5911static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5912 u32 changed)
5913{
5914 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5915 tHalHandle hHal = pHddCtx->hHal;
5916
5917 ENTER();
5918
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005919 if ( pHddCtx->isLogpInProgress )
5920 {
5921 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5922 "%s:LOGP in Progress. Ignore!!!", __func__);
5923 return -EAGAIN;
5924 }
5925
Jeff Johnson295189b2012-06-20 16:38:30 -07005926 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
5927 {
5928 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
5929 WNI_CFG_RTS_THRESHOLD_STAMAX :
5930 wiphy->rts_threshold;
5931
5932 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
5933 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
5934 {
5935 hddLog(VOS_TRACE_LEVEL_ERROR,
5936 "%s: Invalid RTS Threshold value %hu",
5937 __func__, rts_threshold);
5938 return -EINVAL;
5939 }
5940
5941 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
5942 rts_threshold, ccmCfgSetCallback,
5943 eANI_BOOLEAN_TRUE))
5944 {
5945 hddLog(VOS_TRACE_LEVEL_ERROR,
5946 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
5947 __func__, rts_threshold);
5948 return -EIO;
5949 }
5950
5951 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
5952 rts_threshold);
5953 }
5954
5955 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
5956 {
5957 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
5958 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
5959 wiphy->frag_threshold;
5960
5961 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
5962 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
5963 {
5964 hddLog(VOS_TRACE_LEVEL_ERROR,
5965 "%s: Invalid frag_threshold value %hu", __func__,
5966 frag_threshold);
5967 return -EINVAL;
5968 }
5969
5970 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
5971 frag_threshold, ccmCfgSetCallback,
5972 eANI_BOOLEAN_TRUE))
5973 {
5974 hddLog(VOS_TRACE_LEVEL_ERROR,
5975 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
5976 __func__, frag_threshold);
5977 return -EIO;
5978 }
5979
5980 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
5981 frag_threshold);
5982 }
5983
5984 if ((changed & WIPHY_PARAM_RETRY_SHORT)
5985 || (changed & WIPHY_PARAM_RETRY_LONG))
5986 {
5987 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
5988 wiphy->retry_short :
5989 wiphy->retry_long;
5990
5991 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
5992 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
5993 {
5994 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
5995 __func__, retry_value);
5996 return -EINVAL;
5997 }
5998
5999 if (changed & WIPHY_PARAM_RETRY_SHORT)
6000 {
6001 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
6002 retry_value, ccmCfgSetCallback,
6003 eANI_BOOLEAN_TRUE))
6004 {
6005 hddLog(VOS_TRACE_LEVEL_ERROR,
6006 "%s: ccmCfgSetInt failed for long retry count %hu",
6007 __func__, retry_value);
6008 return -EIO;
6009 }
6010 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
6011 __func__, retry_value);
6012 }
6013 else if (changed & WIPHY_PARAM_RETRY_SHORT)
6014 {
6015 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
6016 retry_value, ccmCfgSetCallback,
6017 eANI_BOOLEAN_TRUE))
6018 {
6019 hddLog(VOS_TRACE_LEVEL_ERROR,
6020 "%s: ccmCfgSetInt failed for short retry count %hu",
6021 __func__, retry_value);
6022 return -EIO;
6023 }
6024 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
6025 __func__, retry_value);
6026 }
6027 }
6028
6029 return 0;
6030}
6031
6032/*
6033 * FUNCTION: wlan_hdd_cfg80211_set_txpower
6034 * This function is used to set the txpower
6035 */
6036static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
6037#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
6038 enum tx_power_setting type,
6039#else
6040 enum nl80211_tx_power_setting type,
6041#endif
6042 int dbm)
6043{
6044 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6045 tHalHandle hHal = pHddCtx->hHal;
6046 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
6047 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
6048
6049 ENTER();
6050
6051 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
6052 dbm, ccmCfgSetCallback,
6053 eANI_BOOLEAN_TRUE))
6054 {
6055 hddLog(VOS_TRACE_LEVEL_ERROR,
6056 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
6057 return -EIO;
6058 }
6059
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006060 if ( pHddCtx->isLogpInProgress )
6061 {
6062 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6063 "%s:LOGP in Progress. Ignore!!!", __func__);
6064 return -EAGAIN;
6065 }
6066
Jeff Johnson295189b2012-06-20 16:38:30 -07006067 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
6068 dbm);
6069
6070 switch(type)
6071 {
6072 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
6073 /* Fall through */
6074 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
6075 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
6076 {
6077 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
6078 __func__);
6079 return -EIO;
6080 }
6081 break;
6082 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
6083 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
6084 __func__);
6085 return -EOPNOTSUPP;
6086 break;
6087 default:
6088 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
6089 __func__, type);
6090 return -EIO;
6091 }
6092
6093 return 0;
6094}
6095
6096/*
6097 * FUNCTION: wlan_hdd_cfg80211_get_txpower
6098 * This function is used to read the txpower
6099 */
6100static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
6101{
6102
6103 hdd_adapter_t *pAdapter;
6104 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6105
Jeff Johnsone7245742012-09-05 17:12:55 -07006106 ENTER();
6107
Jeff Johnson295189b2012-06-20 16:38:30 -07006108 if (NULL == pHddCtx)
6109 {
6110 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
6111 *dbm = 0;
6112 return -ENOENT;
6113 }
6114
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006115 if ( pHddCtx->isLogpInProgress )
6116 {
6117 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6118 "%s:LOGP in Progress. Ignore!!!", __func__);
6119 return -EAGAIN;
6120 }
6121
Jeff Johnson295189b2012-06-20 16:38:30 -07006122 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
6123 if (NULL == pAdapter)
6124 {
6125 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
6126 return -ENOENT;
6127 }
6128
6129 wlan_hdd_get_classAstats(pAdapter);
6130 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
6131
Jeff Johnsone7245742012-09-05 17:12:55 -07006132 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006133 return 0;
6134}
6135
6136static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
6137 u8* mac, struct station_info *sinfo)
6138{
6139 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
6140 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6141 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
6142 tANI_U8 rate_flags;
6143
6144 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6145 hdd_config_t *pCfg = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07006146
6147 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
6148 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
6149 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
6150 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
6151 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
6152 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
6153 tANI_U16 maxRate = 0;
6154 tANI_U16 myRate;
6155 tANI_U16 currentRate = 0;
6156 tANI_U8 maxSpeedMCS = 0;
6157 tANI_U8 maxMCSIdx = 0;
6158 tANI_U8 rateFlag = 1;
6159 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006160 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07006161
Jeff Johnsone7245742012-09-05 17:12:55 -07006162 ENTER();
6163
Jeff Johnson295189b2012-06-20 16:38:30 -07006164 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
6165 (0 == ssidlen))
6166 {
6167 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
6168 " Invalid ssidlen, %d", __func__, ssidlen);
6169 /*To keep GUI happy*/
6170 return 0;
6171 }
6172
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006173 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6174 {
6175 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6176 "%s:LOGP in Progress. Ignore!!!", __func__);
6177 return -EAGAIN;
6178 }
6179
Jeff Johnson295189b2012-06-20 16:38:30 -07006180 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
6181 sinfo->filled |= STATION_INFO_SIGNAL;
6182
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006183 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006184 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
6185
6186 //convert to the UI units of 100kbps
6187 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
6188
6189#ifdef LINKSPEED_DEBUG_ENABLED
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006190 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 -07006191 sinfo->signal,
6192 pCfg->reportMaxLinkSpeed,
6193 myRate,
6194 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006195 (int) pCfg->linkSpeedRssiMid,
6196 (int) pCfg->linkSpeedRssiLow,
6197 (int) rate_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07006198#endif //LINKSPEED_DEBUG_ENABLED
6199
6200 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
6201 {
6202 // we do not want to necessarily report the current speed
6203 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
6204 {
6205 // report the max possible speed
6206 rssidx = 0;
6207 }
6208 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
6209 {
6210 // report the max possible speed with RSSI scaling
6211 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
6212 {
6213 // report the max possible speed
6214 rssidx = 0;
6215 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006216 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07006217 {
6218 // report middle speed
6219 rssidx = 1;
6220 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006221 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
6222 {
6223 // report middle speed
6224 rssidx = 2;
6225 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006226 else
6227 {
6228 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006229 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07006230 }
6231 }
6232 else
6233 {
6234 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
6235 hddLog(VOS_TRACE_LEVEL_ERROR,
6236 "%s: Invalid value for reportMaxLinkSpeed: %u",
6237 __func__, pCfg->reportMaxLinkSpeed);
6238 rssidx = 0;
6239 }
6240
6241 maxRate = 0;
6242
6243 /* Get Basic Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306244 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_OPERATIONAL_RATE_SET,
6245 OperationalRates, &ORLeng))
6246 {
6247 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6248 /*To keep GUI happy*/
6249 return 0;
6250 }
6251
Jeff Johnson295189b2012-06-20 16:38:30 -07006252 for (i = 0; i < ORLeng; i++)
6253 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006254 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006255 {
6256 /* Validate Rate Set */
6257 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
6258 {
6259 currentRate = supported_data_rate[j].supported_rate[rssidx];
6260 break;
6261 }
6262 }
6263 /* Update MAX rate */
6264 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6265 }
6266
6267 /* Get Extended Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306268 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
6269 ExtendedRates, &ERLeng))
6270 {
6271 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6272 /*To keep GUI happy*/
6273 return 0;
6274 }
6275
Jeff Johnson295189b2012-06-20 16:38:30 -07006276 for (i = 0; i < ERLeng; i++)
6277 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006278 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006279 {
6280 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
6281 {
6282 currentRate = supported_data_rate[j].supported_rate[rssidx];
6283 break;
6284 }
6285 }
6286 /* Update MAX rate */
6287 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6288 }
6289
6290 /* Get MCS Rate Set -- but only if we are connected at MCS
6291 rates or if we are always reporting max speed or if we have
6292 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006293 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07006294 {
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306295 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_CURRENT_MCS_SET,
6296 MCSRates, &MCSLeng))
6297 {
6298 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6299 /*To keep GUI happy*/
6300 return 0;
6301 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006302 rateFlag = 0;
6303 if (rate_flags & eHAL_TX_RATE_HT40)
6304 {
6305 rateFlag |= 1;
6306 }
6307 if (rate_flags & eHAL_TX_RATE_SGI)
6308 {
6309 rateFlag |= 2;
6310 }
6311
6312 for (i = 0; i < MCSLeng; i++)
6313 {
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006314 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
6315 for (j = 0; j < temp; j++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006316 {
6317 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
6318 {
6319 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
6320 break;
6321 }
6322 }
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006323 if ((j < temp) && (currentRate > maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006324 {
6325 maxRate = currentRate;
6326 maxSpeedMCS = 1;
6327 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
6328 }
6329 }
6330 }
6331
6332 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006333 if (((maxRate < myRate) && (0 == rssidx)) ||
6334 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006335 {
6336 maxRate = myRate;
6337 if (rate_flags & eHAL_TX_RATE_LEGACY)
6338 {
6339 maxSpeedMCS = 0;
6340 }
6341 else
6342 {
6343 maxSpeedMCS = 1;
6344 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6345 }
6346 }
6347
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006348 if ((!maxSpeedMCS) || (0 != rssidx))
Jeff Johnson295189b2012-06-20 16:38:30 -07006349 {
6350 sinfo->txrate.legacy = maxRate;
6351#ifdef LINKSPEED_DEBUG_ENABLED
6352 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
6353#endif //LINKSPEED_DEBUG_ENABLED
6354 }
6355 else
6356 {
6357 sinfo->txrate.mcs = maxMCSIdx;
6358 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6359 if (rate_flags & eHAL_TX_RATE_SGI)
6360 {
6361 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6362 }
6363 if (rate_flags & eHAL_TX_RATE_HT40)
6364 {
6365 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6366 }
6367#ifdef LINKSPEED_DEBUG_ENABLED
6368 pr_info("Reporting MCS rate %d flags %x\n",
6369 sinfo->txrate.mcs,
6370 sinfo->txrate.flags );
6371#endif //LINKSPEED_DEBUG_ENABLED
6372 }
6373 }
6374 else
6375 {
6376 // report current rate instead of max rate
6377
6378 if (rate_flags & eHAL_TX_RATE_LEGACY)
6379 {
6380 //provide to the UI in units of 100kbps
6381 sinfo->txrate.legacy = myRate;
6382#ifdef LINKSPEED_DEBUG_ENABLED
6383 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
6384#endif //LINKSPEED_DEBUG_ENABLED
6385 }
6386 else
6387 {
6388 //must be MCS
6389 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6390 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6391 if (rate_flags & eHAL_TX_RATE_SGI)
6392 {
6393 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6394 }
6395 if (rate_flags & eHAL_TX_RATE_HT40)
6396 {
6397 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6398 }
6399#ifdef LINKSPEED_DEBUG_ENABLED
6400 pr_info("Reporting actual MCS rate %d flags %x\n",
6401 sinfo->txrate.mcs,
6402 sinfo->txrate.flags );
6403#endif //LINKSPEED_DEBUG_ENABLED
6404 }
6405 }
6406 sinfo->filled |= STATION_INFO_TX_BITRATE;
6407
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006408 sinfo->tx_packets =
6409 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
6410 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
6411 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
6412 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
6413
6414 sinfo->tx_retries =
6415 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
6416 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
6417 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
6418 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
6419
6420 sinfo->tx_failed =
6421 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
6422 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
6423 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
6424 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
6425
6426 sinfo->filled |=
6427 STATION_INFO_TX_PACKETS |
6428 STATION_INFO_TX_RETRIES |
6429 STATION_INFO_TX_FAILED;
6430
6431 EXIT();
6432 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006433}
6434
6435static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
6436 struct net_device *dev, bool mode, v_SINT_t timeout)
6437{
6438 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6439 VOS_STATUS vos_status;
6440
Jeff Johnsone7245742012-09-05 17:12:55 -07006441 ENTER();
6442
Jeff Johnson295189b2012-06-20 16:38:30 -07006443 if (NULL == pAdapter)
6444 {
6445 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6446 return -ENODEV;
6447 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006448 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6449 {
6450 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6451 "%s:LOGP in Progress. Ignore!!!", __func__);
6452 return -EAGAIN;
6453 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006454
6455 /**The get power cmd from the supplicant gets updated by the nl only
6456 *on successful execution of the function call
6457 *we are oppositely mapped w.r.t mode in the driver
6458 **/
6459 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
6460
Jeff Johnsone7245742012-09-05 17:12:55 -07006461 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006462 if (VOS_STATUS_E_FAILURE == vos_status)
6463 {
6464 return -EINVAL;
6465 }
6466 return 0;
6467}
6468
6469
6470#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6471static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
6472 struct net_device *netdev,
6473 u8 key_index)
6474{
Jeff Johnsone7245742012-09-05 17:12:55 -07006475 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006476 return 0;
6477}
6478#endif //LINUX_VERSION_CODE
6479
6480#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
6481static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6482 struct net_device *dev,
6483 struct ieee80211_txq_params *params)
6484{
Jeff Johnsone7245742012-09-05 17:12:55 -07006485 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006486 return 0;
6487}
6488#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6489static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6490 struct ieee80211_txq_params *params)
6491{
Jeff Johnsone7245742012-09-05 17:12:55 -07006492 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006493 return 0;
6494}
6495#endif //LINUX_VERSION_CODE
6496
6497static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
6498 struct net_device *dev, u8 *mac)
6499{
6500 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006501 VOS_STATUS vos_status;
6502 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006503
Jeff Johnsone7245742012-09-05 17:12:55 -07006504 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006505 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6506 {
6507 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6508 return -EINVAL;
6509 }
6510
6511 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6512 {
6513 hddLog( LOGE,
6514 "%s: Wlan Load/Unload is in progress", __func__);
6515 return -EBUSY;
6516 }
6517
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006518 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6519 {
6520 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6521 "%s:LOGP in Progress. Ignore!!!", __func__);
6522 return -EAGAIN;
6523 }
6524
Jeff Johnson295189b2012-06-20 16:38:30 -07006525 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006526 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006527 )
6528 {
6529 if( NULL == mac )
6530 {
6531 v_U16_t i;
6532 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
6533 {
6534 if(pAdapter->aStaInfo[i].isUsed)
6535 {
6536 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
6537 hddLog(VOS_TRACE_LEVEL_INFO,
6538 "%s: Delete STA with MAC::"
6539 "%02x:%02x:%02x:%02x:%02x:%02x",
6540 __func__,
6541 macAddr[0], macAddr[1], macAddr[2],
6542 macAddr[3], macAddr[4], macAddr[5]);
6543 hdd_softap_sta_deauth(pAdapter, macAddr);
6544 }
6545 }
6546 }
6547 else
6548 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006549
6550 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
6551 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6552 {
6553 hddLog(VOS_TRACE_LEVEL_INFO,
6554 "%s: Skip this DEL STA as this is not used::"
6555 "%02x:%02x:%02x:%02x:%02x:%02x",
6556 __func__,
6557 mac[0], mac[1], mac[2],
6558 mac[3], mac[4], mac[5]);
6559 return -ENOENT;
6560 }
6561
6562 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
6563 {
6564 hddLog(VOS_TRACE_LEVEL_INFO,
6565 "%s: Skip this DEL STA as deauth is in progress::"
6566 "%02x:%02x:%02x:%02x:%02x:%02x",
6567 __func__,
6568 mac[0], mac[1], mac[2],
6569 mac[3], mac[4], mac[5]);
6570 return -ENOENT;
6571 }
6572
6573 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
6574
Jeff Johnson295189b2012-06-20 16:38:30 -07006575 hddLog(VOS_TRACE_LEVEL_INFO,
6576 "%s: Delete STA with MAC::"
6577 "%02x:%02x:%02x:%02x:%02x:%02x",
6578 __func__,
6579 mac[0], mac[1], mac[2],
6580 mac[3], mac[4], mac[5]);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006581
6582 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
6583 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6584 {
6585 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
6586 hddLog(VOS_TRACE_LEVEL_INFO,
6587 "%s: STA removal failed for ::"
6588 "%02x:%02x:%02x:%02x:%02x:%02x",
6589 __func__,
6590 mac[0], mac[1], mac[2],
6591 mac[3], mac[4], mac[5]);
6592 return -ENOENT;
6593 }
6594
Jeff Johnson295189b2012-06-20 16:38:30 -07006595 }
6596 }
6597
6598 EXIT();
6599
6600 return 0;
6601}
6602
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006603static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
6604 struct net_device *dev, u8 *mac, struct station_parameters *params)
6605{
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006606 int status = -EPERM;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006607#ifdef FEATURE_WLAN_TDLS
6608 u32 mask, set;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006609 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006610 mask = params->sta_flags_mask;
6611
6612 set = params->sta_flags_set;
6613
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006614#ifdef WLAN_FEATURE_TDLS_DEBUG
6615 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6616 "%s: mask 0x%x set 0x%x " MAC_ADDRESS_STR,
6617 __func__, mask, set, MAC_ADDR_ARRAY(mac));
6618#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006619
6620 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6621 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006622 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006623 }
6624 }
6625#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006626 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006627}
6628
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006629
6630#ifdef FEATURE_WLAN_LFR
6631static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006632 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006633{
6634#define MAX_PMKSAIDS_IN_CACHE 8
6635 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -07006636 static tANI_U32 i; // HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006637 tANI_U32 j=0;
6638 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6639 tHalHandle halHandle;
6640 eHalStatus result;
6641 tANI_U8 BSSIDMatched = 0;
6642
Jeff Johnsone7245742012-09-05 17:12:55 -07006643 ENTER();
6644
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006645 // Validate pAdapter
6646 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6647 {
6648 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6649 return -EINVAL;
6650 }
6651
6652 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6653 {
6654 hddLog( LOGE,
6655 "%s: Wlan Load/Unload is in progress", __func__);
6656 return -EBUSY;
6657 }
6658
6659 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6660 {
6661 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6662 "%s:LOGP in Progress. Ignore!!!", __func__);
6663 return -EAGAIN;
6664 }
6665
6666 // Retrieve halHandle
6667 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
6668
6669 for (j = 0; j < i; j++)
6670 {
6671 if(vos_mem_compare(PMKIDCache[j].BSSID,
6672 pmksa->bssid, WNI_CFG_BSSID_LEN))
6673 {
6674 /* BSSID matched previous entry. Overwrite it. */
6675 BSSIDMatched = 1;
6676 vos_mem_copy(PMKIDCache[j].BSSID,
6677 pmksa->bssid, WNI_CFG_BSSID_LEN);
6678 vos_mem_copy(PMKIDCache[j].PMKID,
6679 pmksa->pmkid,
6680 CSR_RSN_PMKID_SIZE);
6681 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006682 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006683 dump_bssid(pmksa->bssid);
6684 dump_pmkid(halHandle, pmksa->pmkid);
6685 break;
6686 }
6687 }
6688
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07006689 /* Check we compared all entries,if then take the first slot now */
6690 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
6691
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006692 if (!BSSIDMatched)
6693 {
6694 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
6695 vos_mem_copy(PMKIDCache[i].BSSID,
6696 pmksa->bssid, ETHER_ADDR_LEN);
6697 vos_mem_copy(PMKIDCache[i].PMKID,
6698 pmksa->pmkid,
6699 CSR_RSN_PMKID_SIZE);
6700 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006701 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006702 dump_bssid(pmksa->bssid);
6703 dump_pmkid(halHandle, pmksa->pmkid);
6704 // Increment the HDD Local Cache index
6705 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
6706 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
6707 }
6708
6709
6710 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
6711 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006712 // __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006713 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006714 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006715 // Finally set the PMKSA ID Cache in CSR
6716 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
6717 PMKIDCache,
6718 i );
6719 return 0;
6720}
6721
6722
6723static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006724 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006725{
Jeff Johnsone7245742012-09-05 17:12:55 -07006726 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006727 // TODO: Implement this later.
6728 return 0;
6729}
6730
6731static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
6732{
Jeff Johnsone7245742012-09-05 17:12:55 -07006733 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006734 // TODO: Implement this later.
6735 return 0;
6736}
6737#endif
6738
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006739#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6740static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
6741 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
6742{
6743 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6744 hdd_station_ctx_t *pHddStaCtx;
6745
6746 if (NULL == pAdapter)
6747 {
6748 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6749 return -ENODEV;
6750 }
6751
6752 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6753
6754 // Added for debug on reception of Re-assoc Req.
6755 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6756 {
6757 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
6758 ftie->ie_len);
6759 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
6760 }
6761
6762#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
6763 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
6764 ftie->ie_len);
6765#endif
6766
6767 // Pass the received FT IEs to SME
Gopichand Nakkala356fb102013-03-06 12:34:04 +05306768 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6769 (const u8 *)ftie->ie,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006770 ftie->ie_len);
6771 return 0;
6772}
6773#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006774
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006775#ifdef FEATURE_WLAN_TDLS
6776static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
6777 u8 *peer, u8 action_code, u8 dialog_token,
6778 u16 status_code, const u8 *buf, size_t len)
6779{
6780
6781 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6782 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006783 u8 peerMac[6];
6784 VOS_STATUS status;
Gopichand Nakkala05922802013-03-14 12:23:19 -07006785 int max_sta_failed = 0;
Hoonki Leea34dd892013-02-05 22:56:02 -08006786 int responder;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006787
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006788 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006789 {
6790 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6791 "Invalid arguments");
6792 return -EINVAL;
6793 }
6794
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006795 if (pHddCtx->isLogpInProgress)
6796 {
6797 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6798 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006799 wlan_hdd_tdls_set_link_status(pAdapter, peer, eTDLS_LINK_IDLE);
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006800 return -EBUSY;
6801 }
6802
Hoonki Lee27511902013-03-14 18:19:06 -07006803 if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006804 {
Hoonki Lee27511902013-03-14 18:19:06 -07006805 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6806 "%s: TDLS mode is disabled OR not enabled in FW."
6807 MAC_ADDRESS_STR " action %d declined.",
6808 __func__, MAC_ADDR_ARRAY(peer), action_code);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006809 return -ENOTSUPP;
6810 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006811
Hoonki Lee27511902013-03-14 18:19:06 -07006812 if ((SIR_MAC_TDLS_SETUP_RSP == action_code) ||
6813 (SIR_MAC_TDLS_DIS_RSP == action_code))
6814 {
6815 wlan_hdd_tdls_set_cap (pAdapter, peerMac, eTDLS_CAP_SUPPORTED);
6816 }
6817
6818 /* other than teardown frame, other mgmt frames are not sent if disabled */
6819 if (SIR_MAC_TDLS_TEARDOWN != action_code)
6820 {
6821 /* if tdls_mode is disabled to respond to peer's request */
6822 if (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode)
6823 {
6824 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6825 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006826 " TDLS mode is disabled. action %d declined.",
6827 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee27511902013-03-14 18:19:06 -07006828
6829 return -ENOTSUPP;
6830 }
6831 }
6832
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006833 if (WLAN_IS_TDLS_SETUP_ACTION(action_code))
6834 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006835 if (wlan_hdd_tdls_is_progress(pAdapter, peer, TRUE))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006836 {
6837 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006838 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006839 " TDLS setup is ongoing. action %d declined.",
6840 __func__, MAC_ADDR_ARRAY(peer), action_code);
6841 return -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006842 }
6843 }
6844
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006845 if (SIR_MAC_TDLS_SETUP_REQ == action_code ||
6846 SIR_MAC_TDLS_SETUP_RSP == action_code )
Lee Hoonkic1262f22013-01-24 21:59:00 -08006847 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006848 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
Lee Hoonkic1262f22013-01-24 21:59:00 -08006849 {
6850 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
6851 we return error code at 'add_station()'. Hence we have this
6852 check again in addtion to add_station().
6853 Anyway, there is no hard to double-check. */
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006854 if (SIR_MAC_TDLS_SETUP_REQ == action_code)
Lee Hoonkic1262f22013-01-24 21:59:00 -08006855 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006856 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6857 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006858 " TDLS Max peer already connected. action %d declined.",
6859 __func__, MAC_ADDR_ARRAY(peer), action_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006860 goto error;
Lee Hoonkic1262f22013-01-24 21:59:00 -08006861 }
6862 else
6863 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006864 /* maximum reached. tweak to send error code to peer and return
6865 error code to supplicant */
Lee Hoonkic1262f22013-01-24 21:59:00 -08006866 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006867 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6868 "%s: " MAC_ADDRESS_STR
6869 " TDLS Max peer already connected send response status %d",
6870 __func__, MAC_ADDR_ARRAY(peer), status_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006871 max_sta_failed = -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006872 /* fall through to send setup resp with failure status
6873 code */
Lee Hoonkic1262f22013-01-24 21:59:00 -08006874 }
6875 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006876 else
6877 {
6878 hddTdlsPeer_t *pTdlsPeer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006879 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006880 if (pTdlsPeer && (eTDLS_LINK_CONNECTED == pTdlsPeer->link_status))
6881 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006882 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006883 "%s:" MAC_ADDRESS_STR " already connected. action %d declined.",
6884 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006885 return -EPERM;
6886 }
6887 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006888 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006889 vos_mem_copy(peerMac, peer, 6);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006890
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006891#ifdef WLAN_FEATURE_TDLS_DEBUG
6892 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006893 "%s: " MAC_ADDRESS_STR " action %d, dialog_token %d status %d, len = %d",
6894 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
6895 action_code, dialog_token, status_code, len);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006896#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006897
Hoonki Leea34dd892013-02-05 22:56:02 -08006898 /*Except teardown responder will not be used so just make 0*/
6899 responder = 0;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006900 if (SIR_MAC_TDLS_TEARDOWN == action_code)
Hoonki Leea34dd892013-02-05 22:56:02 -08006901 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006902 responder = wlan_hdd_tdls_get_responder(pAdapter, peerMac);
6903 if(-1 == responder)
Hoonki Leea34dd892013-02-05 22:56:02 -08006904 {
6905 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006906 "%s: " MAC_ADDRESS_STR " peer doesn't exist dialog_token %d status %d, len = %d",
6907 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
Hoonki Leea34dd892013-02-05 22:56:02 -08006908 dialog_token, status_code, len);
6909 return -EPERM;
6910 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006911 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006912
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006913 INIT_COMPLETION(pAdapter->tdls_mgmt_comp);
6914
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006915 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
Hoonki Leea34dd892013-02-05 22:56:02 -08006916 peerMac, action_code, dialog_token, status_code, (tANI_U8 *)buf, len, responder);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006917
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006918 if (VOS_STATUS_SUCCESS != status)
6919 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006920 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6921 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006922 return -EPERM;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006923 }
6924
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006925 /* not block discovery request, as it is called from timer callback */
6926 if (SIR_MAC_TDLS_DIS_REQ != action_code)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006927 {
Pervinder Singhb4638422013-03-04 22:51:36 -08006928 long rc;
6929
6930 rc = wait_for_completion_interruptible_timeout(&pAdapter->tdls_mgmt_comp,
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006931 msecs_to_jiffies(WAIT_TIME_TDLS_MGMT));
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006932
Pervinder Singhb4638422013-03-04 22:51:36 -08006933 if ((rc <= 0) || (TRUE != pAdapter->mgmtTxCompletionStatus))
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006934 {
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006935 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pervinder Singhb4638422013-03-04 22:51:36 -08006936 "%s: Mgmt Tx Completion failed status %ld TxCompletion %lu",
6937 __func__, rc, pAdapter->mgmtTxCompletionStatus);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006938 return -EPERM;
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006939 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006940 }
6941
Gopichand Nakkala05922802013-03-14 12:23:19 -07006942 if (max_sta_failed)
6943 return max_sta_failed;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006944
Hoonki Leea34dd892013-02-05 22:56:02 -08006945 if (SIR_MAC_TDLS_SETUP_RSP == action_code)
6946 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006947 wlan_hdd_tdls_set_responder(pAdapter, peerMac, TRUE);
Hoonki Leea34dd892013-02-05 22:56:02 -08006948 }
6949 else if (SIR_MAC_TDLS_SETUP_CNF == action_code)
6950 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006951 wlan_hdd_tdls_set_responder(pAdapter, peerMac, FALSE);
Hoonki Leea34dd892013-02-05 22:56:02 -08006952 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006953
6954 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07006955error:
6956 /* max_sta_failed ; we didn't set to CONNECTING for this case,
6957 because we already know that this transaction will be failed,
6958 but we weren't sure if supplicant call DISABLE_LINK or not. So,
6959 to be safe, do not change the state mahine.
6960 */
6961 if(max_sta_failed == 0 &&
6962 (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
6963 wlan_hdd_tdls_set_link_status(pAdapter, peerMac, eTDLS_LINK_IDLE);
6964 return -EPERM;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006965}
6966
6967static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
6968 u8 *peer, enum nl80211_tdls_operation oper)
6969{
6970 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6971 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006972#ifdef WLAN_FEATURE_TDLS_DEBUG
6973 const char *tdls_oper_str[]= {
6974 "NL80211_TDLS_DISCOVERY_REQ",
6975 "NL80211_TDLS_SETUP",
6976 "NL80211_TDLS_TEARDOWN",
6977 "NL80211_TDLS_ENABLE_LINK",
6978 "NL80211_TDLS_DISABLE_LINK",
6979 "NL80211_TDLS_UNKONW_OPER"};
6980#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006981
6982 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6983 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006984 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006985 "Invalid arguments");
6986 return -EINVAL;
6987 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006988
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006989 if (pHddCtx->isLogpInProgress)
6990 {
6991 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6992 "%s:LOGP in Progress. Ignore!!!", __func__);
6993 return -EBUSY;
6994 }
6995
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006996#ifdef WLAN_FEATURE_TDLS_DEBUG
6997 if((int)oper > 4)
6998 oper = 5;
6999
7000 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007001 "%s: " MAC_ADDRESS_STR " %d (%s) ", "tdls_oper",
7002 MAC_ADDR_ARRAY(peer), (int)oper,
7003 tdls_oper_str[(int)oper]);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007004#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007005
7006 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007007 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007008 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007009 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007010 "TDLS Disabled in INI OR not enabled in FW.\
7011 Cannot process TDLS commands \n");
7012 return -ENOTSUPP;
7013 }
7014
7015 switch (oper) {
7016 case NL80211_TDLS_ENABLE_LINK:
7017 {
Hoonki Lee387663d2013-02-05 18:08:43 -08007018 hddTdlsPeer_t *pTdlsPeer;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007019 VOS_STATUS status;
7020
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007021 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007022
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007023 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
7024 "%s: TDLS_LINK_ENABLE " MAC_ADDRESS_STR,
7025 __func__, MAC_ADDR_ARRAY(peer));
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007026
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007027 if ( NULL == pTdlsPeer ) {
7028 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_hdd_tdls_find_peer "
7029 MAC_ADDRESS_STR " failed",
7030 __func__, MAC_ADDR_ARRAY(peer));
7031 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007032 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007033
7034 if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status)
7035 {
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007036 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007037 /* start TDLS client registration with TL */
7038 status = hdd_roamRegisterTDLSSTA( pAdapter, peer, pTdlsPeer->staId, pTdlsPeer->signature);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007039 if (VOS_STATUS_SUCCESS == status)
7040 {
7041 wlan_hdd_tdls_increment_peer_count(pAdapter);
7042 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007043 wlan_hdd_tdls_check_bmps(pAdapter);
7044 }
7045
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007046 }
7047 break;
7048 case NL80211_TDLS_DISABLE_LINK:
Lee Hoonkic1262f22013-01-24 21:59:00 -08007049 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007050 hddTdlsPeer_t *curr_peer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007051
7052 if(NULL != curr_peer)
Lee Hoonkic1262f22013-01-24 21:59:00 -08007053 {
7054 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
7055 pAdapter->sessionId, peer );
Gopichand Nakkala8b00c632013-03-08 19:47:52 -08007056 wlan_hdd_tdls_set_peer_link_status(curr_peer, eTDLS_LINK_IDLE);
Lee Hoonkic1262f22013-01-24 21:59:00 -08007057 }
7058 else
7059 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007060 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7061 "%s: TDLS Peer Station doesn't exist.", __func__);
Lee Hoonkic1262f22013-01-24 21:59:00 -08007062 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08007063 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007064 break;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007065 case NL80211_TDLS_TEARDOWN:
7066 case NL80211_TDLS_SETUP:
7067 case NL80211_TDLS_DISCOVERY_REQ:
7068 /* We don't support in-driver setup/teardown/discovery */
7069 return -ENOTSUPP;
7070 default:
7071 return -ENOTSUPP;
7072 }
7073 return 0;
7074}
Chilam NG571c65a2013-01-19 12:27:36 +05307075
7076int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
7077 struct net_device *dev, u8 *peer)
7078{
7079 hddLog(VOS_TRACE_LEVEL_INFO, "tdls send discover req: %x %x %x %x %x %x",
7080 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5]);
7081
7082 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
7083 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
7084}
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007085#endif
7086
Jeff Johnson295189b2012-06-20 16:38:30 -07007087/* cfg80211_ops */
7088static struct cfg80211_ops wlan_hdd_cfg80211_ops =
7089{
7090 .add_virtual_intf = wlan_hdd_add_virtual_intf,
7091 .del_virtual_intf = wlan_hdd_del_virtual_intf,
7092 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
7093 .change_station = wlan_hdd_change_station,
7094#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
7095 .add_beacon = wlan_hdd_cfg80211_add_beacon,
7096 .del_beacon = wlan_hdd_cfg80211_del_beacon,
7097 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007098#else
7099 .start_ap = wlan_hdd_cfg80211_start_ap,
7100 .change_beacon = wlan_hdd_cfg80211_change_beacon,
7101 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07007102#endif
7103 .change_bss = wlan_hdd_cfg80211_change_bss,
7104 .add_key = wlan_hdd_cfg80211_add_key,
7105 .get_key = wlan_hdd_cfg80211_get_key,
7106 .del_key = wlan_hdd_cfg80211_del_key,
7107 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08007108#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07007109 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08007110#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007111 .scan = wlan_hdd_cfg80211_scan,
7112 .connect = wlan_hdd_cfg80211_connect,
7113 .disconnect = wlan_hdd_cfg80211_disconnect,
7114 .join_ibss = wlan_hdd_cfg80211_join_ibss,
7115 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
7116 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
7117 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
7118 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
Jeff Johnson295189b2012-06-20 16:38:30 -07007119 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
7120 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
7121 .mgmt_tx = wlan_hdd_action,
7122#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7123 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
7124 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
7125 .set_txq_params = wlan_hdd_set_txq_params,
7126#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007127 .get_station = wlan_hdd_cfg80211_get_station,
7128 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
7129 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007130 .add_station = wlan_hdd_cfg80211_add_station,
7131#ifdef FEATURE_WLAN_LFR
7132 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
7133 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
7134 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
7135#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007136#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
7137 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
7138#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007139#ifdef FEATURE_WLAN_TDLS
7140 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
7141 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
7142#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007143};
7144