blob: 00a911ca27e5f0d53575ff4c71d177f0edb94672 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302 * 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*/
Jeff Johnson295189b2012-06-20 16:38:30 -070021
22/**========================================================================
23
24 \file wlan_hdd_cfg80211.c
25
26 \brief WLAN Host Device Driver implementation
27
Gopichand Nakkala747461f2013-04-24 19:24:45 +053028 Copyright 2008 (c) Qualcomm Technologies, Inc. All Rights Reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070029
Gopichand Nakkala747461f2013-04-24 19:24:45 +053030 Qualcomm Technologies Confidential and Proprietary.
Jeff Johnson295189b2012-06-20 16:38:30 -070031
32 ========================================================================*/
33
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070034/**=========================================================================
Jeff Johnson295189b2012-06-20 16:38:30 -070035
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070036 EDIT HISTORY FOR FILE
Jeff Johnson295189b2012-06-20 16:38:30 -070037
38
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070039 This section contains comments describing changes made to the module.
40 Notice that changes are listed in reverse chronological order.
Jeff Johnson295189b2012-06-20 16:38:30 -070041
42
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070043 $Header:$ $DateTime: $ $Author: $
Jeff Johnson295189b2012-06-20 16:38:30 -070044
45
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070046 when who what, where, why
Jeff Johnson295189b2012-06-20 16:38:30 -070047 -------- --- --------------------------------------------------------
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070048 21/12/09 Ashwani Created module.
Jeff Johnson295189b2012-06-20 16:38:30 -070049
50 07/06/10 Kumar Deepak Implemented cfg80211 callbacks for ANDROID
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070051 Ganesh K
Jeff Johnson295189b2012-06-20 16:38:30 -070052 ==========================================================================*/
53
Jeff Johnson295189b2012-06-20 16:38:30 -070054
55#include <linux/version.h>
56#include <linux/module.h>
57#include <linux/kernel.h>
58#include <linux/init.h>
59#include <linux/wireless.h>
60#include <wlan_hdd_includes.h>
61#include <net/arp.h>
62#include <net/cfg80211.h>
63#include <linux/wireless.h>
64#include <wlan_hdd_wowl.h>
65#include <aniGlobal.h>
66#include "ccmApi.h"
67#include "sirParams.h"
68#include "dot11f.h"
69#include "wlan_hdd_assoc.h"
70#include "wlan_hdd_wext.h"
71#include "sme_Api.h"
72#include "wlan_hdd_p2p.h"
73#include "wlan_hdd_cfg80211.h"
74#include "wlan_hdd_hostapd.h"
75#include "sapInternal.h"
76#include "wlan_hdd_softap_tx_rx.h"
77#include "wlan_hdd_main.h"
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +053078#include "wlan_hdd_assoc.h"
Gopichand Nakkala20c4c042013-04-19 22:08:55 +053079#include "wlan_hdd_power.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070080#ifdef WLAN_BTAMP_FEATURE
81#include "bap_hdd_misc.h"
82#endif
83#include <qc_sap_ioctl.h>
Mohit Khanna698ba2a2012-12-04 15:08:18 -080084#ifdef FEATURE_WLAN_TDLS
85#include "wlan_hdd_tdls.h"
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +053086#include "wlan_hdd_wmm.h"
Madan Mohan Koyyalamudice419872013-09-13 19:36:52 +053087#include "wlan_qct_wda.h"
Mohit Khanna698ba2a2012-12-04 15:08:18 -080088#endif
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +053089#include "wlan_nv.h"
Leo Chang6fe1f922013-06-07 19:21:24 -070090#include "wlan_hdd_dev_pwr.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070091
92#define g_mode_rates_size (12)
93#define a_mode_rates_size (8)
94#define FREQ_BASE_80211G (2407)
95#define FREQ_BAND_DIFF_80211G (5)
Jeff Johnson04dd8a82012-06-29 20:41:40 -070096#define MAX_SCAN_SSID 9
Jeff Johnson295189b2012-06-20 16:38:30 -070097#define GET_IE_LEN_IN_BSS_DESC(lenInBss) ( lenInBss + sizeof(lenInBss) - \
98 ((int) OFFSET_OF( tSirBssDescription, ieFields)))
99
100#define HDD2GHZCHAN(freq, chan, flag) { \
101 .band = IEEE80211_BAND_2GHZ, \
102 .center_freq = (freq), \
103 .hw_value = (chan),\
104 .flags = (flag), \
105 .max_antenna_gain = 0 ,\
106 .max_power = 30, \
107}
108
109#define HDD5GHZCHAN(freq, chan, flag) { \
110 .band = IEEE80211_BAND_5GHZ, \
111 .center_freq = (freq), \
112 .hw_value = (chan),\
113 .flags = (flag), \
114 .max_antenna_gain = 0 ,\
115 .max_power = 30, \
116}
117
118#define HDD_G_MODE_RATETAB(rate, rate_id, flag)\
119{\
120 .bitrate = rate, \
121 .hw_value = rate_id, \
122 .flags = flag, \
123}
124
Lee Hoonkic1262f22013-01-24 21:59:00 -0800125#ifndef WLAN_FEATURE_TDLS_DEBUG
126#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_INFO
127#else
128#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_ERROR
129#endif
130
Gopichand Nakkala356fb102013-03-06 12:34:04 +0530131#ifdef WLAN_FEATURE_VOWIFI_11R
132#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
133#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
134#endif
135
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530136static const u32 hdd_cipher_suites[] =
Jeff Johnson295189b2012-06-20 16:38:30 -0700137{
138 WLAN_CIPHER_SUITE_WEP40,
139 WLAN_CIPHER_SUITE_WEP104,
140 WLAN_CIPHER_SUITE_TKIP,
141#ifdef FEATURE_WLAN_CCX
142#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
143 WLAN_CIPHER_SUITE_KRK,
144 WLAN_CIPHER_SUITE_CCMP,
145#else
146 WLAN_CIPHER_SUITE_CCMP,
147#endif
148#ifdef FEATURE_WLAN_WAPI
149 WLAN_CIPHER_SUITE_SMS4,
150#endif
Chet Lanctot186b5732013-03-18 10:26:30 -0700151#ifdef WLAN_FEATURE_11W
152 WLAN_CIPHER_SUITE_AES_CMAC,
153#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700154};
155
156static inline int is_broadcast_ether_addr(const u8 *addr)
157{
158 return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&
159 (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
160}
161
162static struct ieee80211_channel hdd_channels_2_4_GHZ[] =
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530163{
Jeff Johnson295189b2012-06-20 16:38:30 -0700164 HDD2GHZCHAN(2412, 1, 0) ,
165 HDD2GHZCHAN(2417, 2, 0) ,
166 HDD2GHZCHAN(2422, 3, 0) ,
167 HDD2GHZCHAN(2427, 4, 0) ,
168 HDD2GHZCHAN(2432, 5, 0) ,
169 HDD2GHZCHAN(2437, 6, 0) ,
170 HDD2GHZCHAN(2442, 7, 0) ,
171 HDD2GHZCHAN(2447, 8, 0) ,
172 HDD2GHZCHAN(2452, 9, 0) ,
173 HDD2GHZCHAN(2457, 10, 0) ,
174 HDD2GHZCHAN(2462, 11, 0) ,
175 HDD2GHZCHAN(2467, 12, 0) ,
176 HDD2GHZCHAN(2472, 13, 0) ,
177 HDD2GHZCHAN(2484, 14, 0) ,
178};
179
Jeff Johnson295189b2012-06-20 16:38:30 -0700180static struct ieee80211_channel hdd_social_channels_2_4_GHZ[] =
181{
182 HDD2GHZCHAN(2412, 1, 0) ,
183 HDD2GHZCHAN(2437, 6, 0) ,
184 HDD2GHZCHAN(2462, 11, 0) ,
185};
Jeff Johnson295189b2012-06-20 16:38:30 -0700186
187static struct ieee80211_channel hdd_channels_5_GHZ[] =
188{
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700189 HDD5GHZCHAN(4920, 240, 0) ,
190 HDD5GHZCHAN(4940, 244, 0) ,
191 HDD5GHZCHAN(4960, 248, 0) ,
192 HDD5GHZCHAN(4980, 252, 0) ,
193 HDD5GHZCHAN(5040, 208, 0) ,
194 HDD5GHZCHAN(5060, 212, 0) ,
195 HDD5GHZCHAN(5080, 216, 0) ,
Jeff Johnson295189b2012-06-20 16:38:30 -0700196 HDD5GHZCHAN(5180, 36, 0) ,
197 HDD5GHZCHAN(5200, 40, 0) ,
198 HDD5GHZCHAN(5220, 44, 0) ,
199 HDD5GHZCHAN(5240, 48, 0) ,
200 HDD5GHZCHAN(5260, 52, 0) ,
201 HDD5GHZCHAN(5280, 56, 0) ,
202 HDD5GHZCHAN(5300, 60, 0) ,
203 HDD5GHZCHAN(5320, 64, 0) ,
204 HDD5GHZCHAN(5500,100, 0) ,
205 HDD5GHZCHAN(5520,104, 0) ,
206 HDD5GHZCHAN(5540,108, 0) ,
207 HDD5GHZCHAN(5560,112, 0) ,
208 HDD5GHZCHAN(5580,116, 0) ,
209 HDD5GHZCHAN(5600,120, 0) ,
210 HDD5GHZCHAN(5620,124, 0) ,
211 HDD5GHZCHAN(5640,128, 0) ,
212 HDD5GHZCHAN(5660,132, 0) ,
213 HDD5GHZCHAN(5680,136, 0) ,
214 HDD5GHZCHAN(5700,140, 0) ,
215 HDD5GHZCHAN(5745,149, 0) ,
216 HDD5GHZCHAN(5765,153, 0) ,
217 HDD5GHZCHAN(5785,157, 0) ,
218 HDD5GHZCHAN(5805,161, 0) ,
219 HDD5GHZCHAN(5825,165, 0) ,
220};
221
222static struct ieee80211_rate g_mode_rates[] =
223{
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530224 HDD_G_MODE_RATETAB(10, 0x1, 0),
225 HDD_G_MODE_RATETAB(20, 0x2, 0),
226 HDD_G_MODE_RATETAB(55, 0x4, 0),
227 HDD_G_MODE_RATETAB(110, 0x8, 0),
228 HDD_G_MODE_RATETAB(60, 0x10, 0),
229 HDD_G_MODE_RATETAB(90, 0x20, 0),
230 HDD_G_MODE_RATETAB(120, 0x40, 0),
231 HDD_G_MODE_RATETAB(180, 0x80, 0),
232 HDD_G_MODE_RATETAB(240, 0x100, 0),
233 HDD_G_MODE_RATETAB(360, 0x200, 0),
234 HDD_G_MODE_RATETAB(480, 0x400, 0),
Jeff Johnson295189b2012-06-20 16:38:30 -0700235 HDD_G_MODE_RATETAB(540, 0x800, 0),
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530236};
Jeff Johnson295189b2012-06-20 16:38:30 -0700237
238static struct ieee80211_rate a_mode_rates[] =
239{
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530240 HDD_G_MODE_RATETAB(60, 0x10, 0),
241 HDD_G_MODE_RATETAB(90, 0x20, 0),
242 HDD_G_MODE_RATETAB(120, 0x40, 0),
243 HDD_G_MODE_RATETAB(180, 0x80, 0),
244 HDD_G_MODE_RATETAB(240, 0x100, 0),
245 HDD_G_MODE_RATETAB(360, 0x200, 0),
246 HDD_G_MODE_RATETAB(480, 0x400, 0),
Jeff Johnson295189b2012-06-20 16:38:30 -0700247 HDD_G_MODE_RATETAB(540, 0x800, 0),
248};
249
250static struct ieee80211_supported_band wlan_hdd_band_2_4_GHZ =
251{
252 .channels = hdd_channels_2_4_GHZ,
253 .n_channels = ARRAY_SIZE(hdd_channels_2_4_GHZ),
254 .band = IEEE80211_BAND_2GHZ,
255 .bitrates = g_mode_rates,
256 .n_bitrates = g_mode_rates_size,
257 .ht_cap.ht_supported = 1,
258 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
259 | IEEE80211_HT_CAP_GRN_FLD
260 | IEEE80211_HT_CAP_DSSSCCK40
261 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
262 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
263 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
264 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
265 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
266 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
267};
268
Jeff Johnson295189b2012-06-20 16:38:30 -0700269static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_GHZ =
270{
271 .channels = hdd_social_channels_2_4_GHZ,
272 .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_GHZ),
273 .band = IEEE80211_BAND_2GHZ,
274 .bitrates = g_mode_rates,
275 .n_bitrates = g_mode_rates_size,
276 .ht_cap.ht_supported = 1,
277 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
278 | IEEE80211_HT_CAP_GRN_FLD
279 | IEEE80211_HT_CAP_DSSSCCK40
280 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
281 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
282 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
283 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
284 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
285 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
286};
Jeff Johnson295189b2012-06-20 16:38:30 -0700287
288static struct ieee80211_supported_band wlan_hdd_band_5_GHZ =
289{
290 .channels = hdd_channels_5_GHZ,
291 .n_channels = ARRAY_SIZE(hdd_channels_5_GHZ),
292 .band = IEEE80211_BAND_5GHZ,
293 .bitrates = a_mode_rates,
294 .n_bitrates = a_mode_rates_size,
295 .ht_cap.ht_supported = 1,
296 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
297 | IEEE80211_HT_CAP_GRN_FLD
298 | IEEE80211_HT_CAP_DSSSCCK40
299 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
300 | IEEE80211_HT_CAP_SGI_40
301 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
302 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
303 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
304 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
305 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
306 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
307};
308
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530309/* This structure contain information what kind of frame are expected in
Jeff Johnson295189b2012-06-20 16:38:30 -0700310 TX/RX direction for each kind of interface */
311static const struct ieee80211_txrx_stypes
312wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
313 [NL80211_IFTYPE_STATION] = {
314 .tx = 0xffff,
315 .rx = BIT(SIR_MAC_MGMT_ACTION) |
316 BIT(SIR_MAC_MGMT_PROBE_REQ),
317 },
318 [NL80211_IFTYPE_AP] = {
319 .tx = 0xffff,
320 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
321 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
322 BIT(SIR_MAC_MGMT_PROBE_REQ) |
323 BIT(SIR_MAC_MGMT_DISASSOC) |
324 BIT(SIR_MAC_MGMT_AUTH) |
325 BIT(SIR_MAC_MGMT_DEAUTH) |
326 BIT(SIR_MAC_MGMT_ACTION),
327 },
Jeff Johnsonbc006202013-04-29 14:05:30 -0700328 [NL80211_IFTYPE_ADHOC] = {
329 .tx = 0xffff,
330 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
331 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
332 BIT(SIR_MAC_MGMT_PROBE_REQ) |
333 BIT(SIR_MAC_MGMT_DISASSOC) |
334 BIT(SIR_MAC_MGMT_AUTH) |
335 BIT(SIR_MAC_MGMT_DEAUTH) |
336 BIT(SIR_MAC_MGMT_ACTION),
337 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700338 [NL80211_IFTYPE_P2P_CLIENT] = {
339 .tx = 0xffff,
340 .rx = BIT(SIR_MAC_MGMT_ACTION) |
341 BIT(SIR_MAC_MGMT_PROBE_REQ),
342 },
343 [NL80211_IFTYPE_P2P_GO] = {
344 /* This is also same as for SoftAP */
345 .tx = 0xffff,
346 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
347 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
348 BIT(SIR_MAC_MGMT_PROBE_REQ) |
349 BIT(SIR_MAC_MGMT_DISASSOC) |
350 BIT(SIR_MAC_MGMT_AUTH) |
351 BIT(SIR_MAC_MGMT_DEAUTH) |
352 BIT(SIR_MAC_MGMT_ACTION),
353 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700354};
355
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800356#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800357static const struct ieee80211_iface_limit
358wlan_hdd_iface_limit[] = {
359 {
Sunil Ravia72c3992013-01-31 06:12:22 -0800360 /* max = 3 ; Our driver create two interfaces during driver init
361 * wlan0 and p2p0 interfaces. p2p0 is considered as station
362 * interface until a group is formed. In JB architecture, once the
363 * group is formed, interface type of p2p0 is changed to P2P GO or
364 * Client.
365 * When supplicant remove the group, it first issue a set interface
366 * cmd to change the mode back to Station. In JB this works fine as
367 * we advertize two station type interface during driver init.
368 * Some vendors create separate interface for P2P GO/Client,
369 * after group formation(Third one). But while group remove
370 * supplicant first tries to change the mode(3rd interface) to STATION
371 * But as we advertized only two sta type interfaces nl80211 was
372 * returning error for the third one which was leading to failure in
373 * delete interface. Ideally while removing the group, supplicant
374 * should not try to change the 3rd interface mode to Station type.
375 * Till we get a fix in wpa_supplicant, we advertize max STA
376 * interface type to 3
377 */
378 .max = 3,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800379 .types = BIT(NL80211_IFTYPE_STATION),
380 },
381 {
382 .max = 1,
Jeff Johnsonbc006202013-04-29 14:05:30 -0700383 .types = BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP),
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800384 },
385 {
386 .max = 1,
387 .types = BIT(NL80211_IFTYPE_P2P_GO) |
388 BIT(NL80211_IFTYPE_P2P_CLIENT),
389 },
390};
391
392/* By default, only single channel concurrency is allowed */
393static struct ieee80211_iface_combination
394wlan_hdd_iface_combination = {
395 .limits = wlan_hdd_iface_limit,
396 .num_different_channels = 1,
Sunil Ravia72c3992013-01-31 06:12:22 -0800397 /*
398 * max = WLAN_MAX_INTERFACES ; JellyBean architecture creates wlan0
399 * and p2p0 interfaces during driver init
400 * Some vendors create separate interface for P2P operations.
401 * wlan0: STA interface
402 * p2p0: P2P Device interface, action frames goes
403 * through this interface.
404 * p2p-xx: P2P interface, After GO negotiation this interface is
405 * created for p2p operations(GO/CLIENT interface).
406 */
407 .max_interfaces = WLAN_MAX_INTERFACES,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800408 .n_limits = ARRAY_SIZE(wlan_hdd_iface_limit),
409 .beacon_int_infra_match = false,
410};
411#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800412
Jeff Johnson295189b2012-06-20 16:38:30 -0700413static struct cfg80211_ops wlan_hdd_cfg80211_ops;
414
415/* Data rate 100KBPS based on IE Index */
416struct index_data_rate_type
417{
418 v_U8_t beacon_rate_index;
419 v_U16_t supported_rate[4];
420};
421
422/* 11B, 11G Rate table include Basic rate and Extended rate
423 The IDX field is the rate index
424 The HI field is the rate when RSSI is strong or being ignored
425 (in this case we report actual rate)
426 The MID field is the rate when RSSI is moderate
427 (in this case we cap 11b rates at 5.5 and 11g rates at 24)
428 The LO field is the rate when RSSI is low
429 (in this case we don't report rates, actual current rate used)
430 */
431static const struct
432{
433 v_U8_t beacon_rate_index;
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700434 v_U16_t supported_rate[4];
Jeff Johnson295189b2012-06-20 16:38:30 -0700435} supported_data_rate[] =
436{
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700437/* IDX HI HM LM LO (RSSI-based index */
438 {2, { 10, 10, 10, 0}},
439 {4, { 20, 20, 10, 0}},
440 {11, { 55, 20, 10, 0}},
441 {12, { 60, 55, 20, 0}},
442 {18, { 90, 55, 20, 0}},
443 {22, {110, 55, 20, 0}},
444 {24, {120, 90, 60, 0}},
445 {36, {180, 120, 60, 0}},
446 {44, {220, 180, 60, 0}},
447 {48, {240, 180, 90, 0}},
448 {66, {330, 180, 90, 0}},
449 {72, {360, 240, 90, 0}},
450 {96, {480, 240, 120, 0}},
451 {108, {540, 240, 120, 0}}
Jeff Johnson295189b2012-06-20 16:38:30 -0700452};
453
454/* MCS Based rate table */
455static struct index_data_rate_type supported_mcs_rate[] =
456{
457/* MCS L20 L40 S20 S40 */
458 {0, {65, 135, 72, 150}},
459 {1, {130, 270, 144, 300}},
460 {2, {195, 405, 217, 450}},
461 {3, {260, 540, 289, 600}},
462 {4, {390, 810, 433, 900}},
463 {5, {520, 1080, 578, 1200}},
464 {6, {585, 1215, 650, 1350}},
465 {7, {650, 1350, 722, 1500}}
466};
467
Leo Chang6f8870f2013-03-26 18:11:36 -0700468#ifdef WLAN_FEATURE_11AC
469
Gopichand Nakkala4c705372013-04-24 13:20:33 +0530470#define DATA_RATE_11AC_MCS_MASK 0x03
Leo Chang6f8870f2013-03-26 18:11:36 -0700471
472struct index_vht_data_rate_type
473{
474 v_U8_t beacon_rate_index;
Gopichand Nakkala4c705372013-04-24 13:20:33 +0530475 v_U16_t supported_VHT80_rate[2];
476 v_U16_t supported_VHT40_rate[2];
477 v_U16_t supported_VHT20_rate[2];
Leo Chang6f8870f2013-03-26 18:11:36 -0700478};
479
480typedef enum
481{
482 DATA_RATE_11AC_MAX_MCS_7,
483 DATA_RATE_11AC_MAX_MCS_8,
484 DATA_RATE_11AC_MAX_MCS_9,
485 DATA_RATE_11AC_MAX_MCS_NA
486} eDataRate11ACMaxMcs;
487
488/* MCS Based VHT rate table */
489static struct index_vht_data_rate_type supported_vht_mcs_rate[] =
490{
Gopichand Nakkala4c705372013-04-24 13:20:33 +0530491/* MCS L80 S80 L40 S40 L20 S40*/
492 {0, {293, 325}, {135, 150}, {65, 72}},
493 {1, {585, 650}, {270, 300}, {130, 144}},
494 {2, {878, 975}, {405, 450}, {195, 217}},
495 {3, {1170, 1300}, {540, 600}, {260, 289}},
496 {4, {1755, 1950}, {810, 900}, {390, 433}},
497 {5, {2340, 2600}, {1080, 1200}, {520, 578}},
498 {6, {2633, 2925}, {1215, 1350}, {585, 650}},
499 {7, {2925, 3250}, {1350, 1500}, {650, 722}},
500 {8, {3510, 3900}, {1620, 1800}, {780, 867}},
501 {9, {3900, 4333}, {1800, 2000}, {780, 867}}
Leo Chang6f8870f2013-03-26 18:11:36 -0700502};
503#endif /* WLAN_FEATURE_11AC */
504
Jeff Johnson295189b2012-06-20 16:38:30 -0700505extern struct net_device_ops net_ops_struct;
506
Leo Chang9056f462013-08-01 19:21:11 -0700507#ifdef WLAN_NL80211_TESTMODE
508enum wlan_hdd_tm_attr
509{
510 WLAN_HDD_TM_ATTR_INVALID = 0,
511 WLAN_HDD_TM_ATTR_CMD = 1,
512 WLAN_HDD_TM_ATTR_DATA = 2,
513 WLAN_HDD_TM_ATTR_TYPE = 3,
514 /* keep last */
515 WLAN_HDD_TM_ATTR_AFTER_LAST,
516 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
517};
518
519enum wlan_hdd_tm_cmd
520{
521 WLAN_HDD_TM_CMD_WLAN_HB = 1,
522};
523
524#define WLAN_HDD_TM_DATA_MAX_LEN 5000
525
526static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] =
527{
528 [WLAN_HDD_TM_ATTR_CMD] = { .type = NLA_U32 },
529 [WLAN_HDD_TM_ATTR_DATA] = { .type = NLA_BINARY,
530 .len = WLAN_HDD_TM_DATA_MAX_LEN },
531};
532#endif /* WLAN_NL80211_TESTMODE */
533
Jeff Johnson295189b2012-06-20 16:38:30 -0700534/*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530535 * FUNCTION: wlan_hdd_cfg80211_wiphy_alloc
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530536 * This function is called by hdd_wlan_startup()
537 * during initialization.
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530538 * This function is used to allocate wiphy structure.
Jeff Johnson295189b2012-06-20 16:38:30 -0700539 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530540struct wiphy *wlan_hdd_cfg80211_wiphy_alloc(int priv_size)
Jeff Johnson295189b2012-06-20 16:38:30 -0700541{
542 struct wiphy *wiphy;
543 ENTER();
544
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530545 /*
546 * Create wiphy device
Jeff Johnson295189b2012-06-20 16:38:30 -0700547 */
548 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
549
550 if (!wiphy)
551 {
552 /* Print error and jump into err label and free the memory */
553 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__);
554 return NULL;
555 }
556
557 return wiphy;
558}
559
560/*
561 * FUNCTION: wlan_hdd_cfg80211_update_band
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530562 * This function is called from the supplicant through a
Jeff Johnson295189b2012-06-20 16:38:30 -0700563 * private ioctl to change the band value
564 */
565int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
566{
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530567 int i, j;
568 eNVChannelEnabledType channelEnabledState;
569
Jeff Johnsone7245742012-09-05 17:12:55 -0700570 ENTER();
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530571 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
Jeff Johnson295189b2012-06-20 16:38:30 -0700572 {
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530573
574 if (NULL == wiphy->bands[i])
575 {
576 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[i] is NULL, i = %d",
577 __func__, i);
578 continue;
579 }
580
581 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
582 {
583 struct ieee80211_supported_band *band = wiphy->bands[i];
584
585 channelEnabledState = vos_nv_getChannelEnabledState(
586 band->channels[j].hw_value);
587
588 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) // 5G only
589 {
590 // Enable Social channels for P2P
591 if (WLAN_HDD_IS_SOCIAL_CHANNEL(band->channels[j].center_freq) &&
592 NV_CHANNEL_ENABLE == channelEnabledState)
593 band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED;
594 else
595 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
596 continue;
597 }
598 else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == eBand) // 2G only
599 {
600 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
601 continue;
602 }
603
604 if (NV_CHANNEL_DISABLE == channelEnabledState ||
605 NV_CHANNEL_INVALID == channelEnabledState)
606 {
607 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
608 }
609 else if (NV_CHANNEL_DFS == channelEnabledState)
610 {
611 band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED;
612 band->channels[j].flags |= IEEE80211_CHAN_RADAR;
613 }
614 else
615 {
616 band->channels[j].flags &= ~(IEEE80211_CHAN_DISABLED
617 |IEEE80211_CHAN_RADAR);
618 }
619 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700620 }
621 return 0;
622}
623/*
624 * FUNCTION: wlan_hdd_cfg80211_init
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530625 * This function is called by hdd_wlan_startup()
626 * during initialization.
Jeff Johnson295189b2012-06-20 16:38:30 -0700627 * This function is used to initialize and register wiphy structure.
628 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530629int wlan_hdd_cfg80211_init(struct device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700630 struct wiphy *wiphy,
631 hdd_config_t *pCfg
632 )
633{
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530634 int i, j;
Jeff Johnsone7245742012-09-05 17:12:55 -0700635 ENTER();
636
Jeff Johnson295189b2012-06-20 16:38:30 -0700637 /* Now bind the underlying wlan device with wiphy */
638 set_wiphy_dev(wiphy, dev);
639
640 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
Amar Singhalfddc28c2013-09-05 13:03:40 -0700641
642 /* This will disable updating of NL channels from passive to
643 * active if a beacon is received on passive channel. */
644 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhalf0073192013-09-20 12:34:56 -0700645
Amar Singhalfddc28c2013-09-05 13:03:40 -0700646
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700647#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700648 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
649 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
650 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
Jeff Johnsone7245742012-09-05 17:12:55 -0700651 | WIPHY_FLAG_OFFCHAN_TX;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700652#endif
Srinivas Girigowda640728a2013-03-28 12:21:54 -0700653#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
654 if (pCfg->isFastTransitionEnabled
James Zmuda77fb5ae2013-01-29 08:00:17 -0800655#ifdef FEATURE_WLAN_LFR
Srinivas Girigowda640728a2013-03-28 12:21:54 -0700656 || pCfg->isFastRoamIniFeatureEnabled
657#endif
658#ifdef FEATURE_WLAN_CCX
659 || pCfg->isCcxIniFeatureEnabled
660#endif
661 )
662 {
663 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
664 }
James Zmuda77fb5ae2013-01-29 08:00:17 -0800665#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800666#ifdef FEATURE_WLAN_TDLS
667 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
668 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
669#endif
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +0530670#ifdef FEATURE_WLAN_SCAN_PNO
671 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
Madan Mohan Koyyalamudi75de0102013-09-17 14:56:29 +0530672 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +0530673 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
Madan Mohan Koyyalamudia7765d52013-09-18 16:49:56 +0530674 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +0530675#endif/*FEATURE_WLAN_SCAN_PNO*/
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800676
Amar Singhalfddc28c2013-09-05 13:03:40 -0700677#ifdef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700678 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
679 driver can still register regulatory callback and
Amar Singhalfddc28c2013-09-05 13:03:40 -0700680 it will get regulatory settings in wiphy->band[], but
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700681 driver need to determine what to do with both
682 regulatory settings */
Amar Singhalfddc28c2013-09-05 13:03:40 -0700683
684 wiphy->reg_notifier = wlan_hdd_linux_reg_notifier;
685#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700686
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530687 wiphy->max_scan_ssids = MAX_SCAN_SSID;
688
Madan Mohan Koyyalamudi6815b162013-07-19 17:17:46 +0530689 wiphy->max_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Jeff Johnson295189b2012-06-20 16:38:30 -0700690
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +0530691 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
692
Jeff Johnson295189b2012-06-20 16:38:30 -0700693 /* Supports STATION & AD-HOC modes right now */
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530694 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -0700695 | BIT(NL80211_IFTYPE_ADHOC)
Jeff Johnson295189b2012-06-20 16:38:30 -0700696 | BIT(NL80211_IFTYPE_P2P_CLIENT)
697 | BIT(NL80211_IFTYPE_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -0700698 | BIT(NL80211_IFTYPE_AP);
699
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800700#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800701 if( pCfg->enableMCC )
702 {
703 /* Currently, supports up to two channels */
704 wlan_hdd_iface_combination.num_different_channels = 2;
705
706 if( !pCfg->allowMCCGODiffBI )
707 wlan_hdd_iface_combination.beacon_int_infra_match = true;
708
709 }
710 wiphy->iface_combinations = &wlan_hdd_iface_combination;
711 wiphy->n_iface_combinations = 1;
712#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800713
Jeff Johnson295189b2012-06-20 16:38:30 -0700714 /* Before registering we need to update the ht capabilitied based
715 * on ini values*/
716 if( !pCfg->ShortGI20MhzEnable )
717 {
718 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
719 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
720 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
721 }
722
723 if( !pCfg->ShortGI40MhzEnable )
724 {
725 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
726 }
727
728 if( !pCfg->nChannelBondingMode5GHz )
729 {
730 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
731 }
732
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530733 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
734 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
735
736 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
737 {
738
739 if (NULL == wiphy->bands[i])
740 {
741 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[i] is NULL, i = %d",
742 __func__, i);
743 continue;
744 }
745
746 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
747 {
748 struct ieee80211_supported_band *band = wiphy->bands[i];
749
750 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == pCfg->nBandCapability) // 5G only
751 {
752 // Enable social channels for P2P
753 if (WLAN_HDD_IS_SOCIAL_CHANNEL(band->channels[j].center_freq))
754 band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED;
755 else
756 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
757 continue;
758 }
759 else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == pCfg->nBandCapability) // 2G only
760 {
761 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
762 continue;
763 }
764 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700765 }
766 /*Initialise the supported cipher suite details*/
767 wiphy->cipher_suites = hdd_cipher_suites;
768 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
769
770 /*signal strength in mBm (100*dBm) */
771 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
772
773#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -0700774 wiphy->max_remain_on_channel_duration = 1000;
775#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700776
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530777 EXIT();
778 return 0;
779}
780
781/* In this function we are registering wiphy. */
782int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
783{
784 ENTER();
785 /* Register our wiphy dev with cfg80211 */
Jeff Johnson295189b2012-06-20 16:38:30 -0700786 if (0 > wiphy_register(wiphy))
787 {
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530788 /* print error */
Jeff Johnson295189b2012-06-20 16:38:30 -0700789 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
790 return -EIO;
791 }
792
793 EXIT();
794 return 0;
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530795}
Jeff Johnson295189b2012-06-20 16:38:30 -0700796
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530797/* In this function we are updating channel list when,
798 regulatory domain is FCC and country code is US.
799 Here In FCC standard 5GHz UNII-1 Bands are indoor only.
800 As per FCC smart phone is not a indoor device.
801 GO should not opeate on indoor channels */
802void wlan_hdd_cfg80211_update_reg_info(struct wiphy *wiphy)
803{
804 int j;
805 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
806 tANI_U8 defaultCountryCode[3] = SME_INVALID_COUNTRY_CODE;
807 //Default counrtycode from NV at the time of wiphy initialization.
808 if (eHAL_STATUS_SUCCESS != sme_GetDefaultCountryCodeFrmNv(pHddCtx->hHal,
809 &defaultCountryCode[0]))
810 {
811 hddLog(LOGE, FL("%s Failed to get default country code from NV"));
812 }
813 if ((defaultCountryCode[0]== 'U') && (defaultCountryCode[1]=='S'))
814 {
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530815 if (NULL == wiphy->bands[IEEE80211_BAND_5GHZ])
816 {
817 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[IEEE80211_BAND_5GHZ] is NULL",__func__ );
818 return;
819 }
820 for (j = 0; j < wiphy->bands[IEEE80211_BAND_5GHZ]->n_channels; j++)
821 {
822 struct ieee80211_supported_band *band = wiphy->bands[IEEE80211_BAND_5GHZ];
823 // Mark UNII -1 band channel as passive
824 if (WLAN_HDD_CHANNEL_IN_UNII_1_BAND(band->channels[j].center_freq))
825 band->channels[j].flags |= IEEE80211_CHAN_PASSIVE_SCAN;
826 }
827 }
828}
829
Jeff Johnson295189b2012-06-20 16:38:30 -0700830/* In this function we will do all post VOS start initialization.
831 In this function we will register for all frame in which supplicant
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530832 is interested.
Jeff Johnson295189b2012-06-20 16:38:30 -0700833*/
834void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
835{
Jeff Johnson295189b2012-06-20 16:38:30 -0700836 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
837 /* Register for all P2P action, public action etc frames */
838 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
839
Jeff Johnsone7245742012-09-05 17:12:55 -0700840 ENTER();
841
Jeff Johnson295189b2012-06-20 16:38:30 -0700842 /* Right now we are registering these frame when driver is getting
843 initialized. Once we will move to 2.6.37 kernel, in which we have
844 frame register ops, we will move this code as a part of that */
845 /* GAS Initial Request */
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530846 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
Jeff Johnson295189b2012-06-20 16:38:30 -0700847 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
848
849 /* GAS Initial Response */
850 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
851 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530852
Jeff Johnson295189b2012-06-20 16:38:30 -0700853 /* GAS Comeback Request */
854 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
855 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
856
857 /* GAS Comeback Response */
858 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
859 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
860
861 /* P2P Public Action */
862 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530863 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
Jeff Johnson295189b2012-06-20 16:38:30 -0700864 P2P_PUBLIC_ACTION_FRAME_SIZE );
865
866 /* P2P Action */
867 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
868 (v_U8_t*)P2P_ACTION_FRAME,
869 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -0700870
Gopichand Nakkalae3d56e72013-04-21 23:33:32 +0530871 /* WNM BSS Transition Request frame */
872 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
873 (v_U8_t*)WNM_BSS_ACTION_FRAME,
874 WNM_BSS_ACTION_FRAME_SIZE );
875
Chet Lanctot186b5732013-03-18 10:26:30 -0700876#ifdef WLAN_FEATURE_11W
877 /* SA Query Response Action Frame */
878 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
879 (v_U8_t*)SA_QUERY_FRAME_RSP,
880 SA_QUERY_FRAME_RSP_SIZE );
881#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -0700882}
883
884void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
885{
Jeff Johnson295189b2012-06-20 16:38:30 -0700886 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
887 /* Register for all P2P action, public action etc frames */
888 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
889
Jeff Johnsone7245742012-09-05 17:12:55 -0700890 ENTER();
891
Jeff Johnson295189b2012-06-20 16:38:30 -0700892 /* Right now we are registering these frame when driver is getting
893 initialized. Once we will move to 2.6.37 kernel, in which we have
894 frame register ops, we will move this code as a part of that */
895 /* GAS Initial Request */
896
897 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
898 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
899
900 /* GAS Initial Response */
901 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
902 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530903
Jeff Johnson295189b2012-06-20 16:38:30 -0700904 /* GAS Comeback Request */
905 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
906 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
907
908 /* GAS Comeback Response */
909 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
910 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
911
912 /* P2P Public Action */
913 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530914 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
Jeff Johnson295189b2012-06-20 16:38:30 -0700915 P2P_PUBLIC_ACTION_FRAME_SIZE );
916
917 /* P2P Action */
918 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
919 (v_U8_t*)P2P_ACTION_FRAME,
920 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -0700921
922#ifdef WLAN_FEATURE_11W
923 /* SA Query Response Action Frame */
924 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
925 (v_U8_t*)SA_QUERY_FRAME_RSP,
926 SA_QUERY_FRAME_RSP_SIZE );
927#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -0700928}
929
930#ifdef FEATURE_WLAN_WAPI
931void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
932 const u8 *mac_addr, u8 *key , int key_Len)
933{
934 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
935 tCsrRoamSetKey setKey;
936 v_BOOL_t isConnected = TRUE;
937 int status = 0;
938 v_U32_t roamId= 0xFF;
939 tANI_U8 *pKeyPtr = NULL;
940 int n = 0;
941
942 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
943 __func__,pAdapter->device_mode);
944
Gopichand Nakkalae7480202013-02-11 15:24:22 +0530945 vos_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Jeff Johnson295189b2012-06-20 16:38:30 -0700946 setKey.keyId = key_index; // Store Key ID
947 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
948 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
949 setKey.paeRole = 0 ; // the PAE role
950 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
951 {
952 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
953 }
954 else
955 {
956 isConnected = hdd_connIsConnected(pHddStaCtx);
957 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
958 }
959 setKey.keyLength = key_Len;
960 pKeyPtr = setKey.Key;
961 memcpy( pKeyPtr, key, key_Len);
962
963 hddLog(VOS_TRACE_LEVEL_INFO,"\n%s: WAPI KEY LENGTH:0x%04x",
964 __func__, key_Len);
965 for (n = 0 ; n < key_Len; n++)
966 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
967 __func__,n,setKey.Key[n]);
968
969 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
970 if ( isConnected )
971 {
972 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
973 pAdapter->sessionId, &setKey, &roamId );
974 }
975 if ( status != 0 )
976 {
977 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
978 "[%4d] sme_RoamSetKey returned ERROR status= %d",
979 __LINE__, status );
980 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
981 }
982}
983#endif /* FEATURE_WLAN_WAPI*/
984
985#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530986int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -0700987 beacon_data_t **ppBeacon,
988 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700989#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530990int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700991 beacon_data_t **ppBeacon,
992 struct cfg80211_beacon_data *params,
993 int dtim_period)
994#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530995{
Jeff Johnson295189b2012-06-20 16:38:30 -0700996 int size;
997 beacon_data_t *beacon = NULL;
998 beacon_data_t *old = NULL;
999 int head_len,tail_len;
1000
Jeff Johnsone7245742012-09-05 17:12:55 -07001001 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07001002 if (params->head && !params->head_len)
1003 return -EINVAL;
1004
1005 old = pAdapter->sessionCtx.ap.beacon;
1006
1007 if (!params->head && !old)
1008 return -EINVAL;
1009
1010 if (params->tail && !params->tail_len)
1011 return -EINVAL;
1012
1013#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
1014 /* Kernel 3.0 is not updating dtim_period for set beacon */
1015 if (!params->dtim_period)
1016 return -EINVAL;
1017#endif
1018
1019 if(params->head)
1020 head_len = params->head_len;
1021 else
1022 head_len = old->head_len;
1023
1024 if(params->tail || !old)
1025 tail_len = params->tail_len;
1026 else
1027 tail_len = old->tail_len;
1028
1029 size = sizeof(beacon_data_t) + head_len + tail_len;
1030
1031 beacon = kzalloc(size, GFP_KERNEL);
1032
1033 if( beacon == NULL )
1034 return -ENOMEM;
1035
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001036#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001037 if(params->dtim_period || !old )
1038 beacon->dtim_period = params->dtim_period;
1039 else
1040 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001041#else
1042 if(dtim_period || !old )
1043 beacon->dtim_period = dtim_period;
1044 else
1045 beacon->dtim_period = old->dtim_period;
1046#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301047
Jeff Johnson295189b2012-06-20 16:38:30 -07001048 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
1049 beacon->tail = beacon->head + head_len;
1050 beacon->head_len = head_len;
1051 beacon->tail_len = tail_len;
1052
1053 if(params->head) {
1054 memcpy (beacon->head,params->head,beacon->head_len);
1055 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301056 else {
Jeff Johnson295189b2012-06-20 16:38:30 -07001057 if(old)
1058 memcpy (beacon->head,old->head,beacon->head_len);
1059 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301060
Jeff Johnson295189b2012-06-20 16:38:30 -07001061 if(params->tail) {
1062 memcpy (beacon->tail,params->tail,beacon->tail_len);
1063 }
1064 else {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301065 if(old)
Jeff Johnson295189b2012-06-20 16:38:30 -07001066 memcpy (beacon->tail,old->tail,beacon->tail_len);
1067 }
1068
1069 *ppBeacon = beacon;
1070
1071 kfree(old);
1072
1073 return 0;
1074
1075}
Jeff Johnson295189b2012-06-20 16:38:30 -07001076
1077v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
1078{
1079 int left = length;
1080 v_U8_t *ptr = pIes;
1081 v_U8_t elem_id,elem_len;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301082
Jeff Johnson295189b2012-06-20 16:38:30 -07001083 while(left >= 2)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301084 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001085 elem_id = ptr[0];
1086 elem_len = ptr[1];
1087 left -= 2;
1088 if(elem_len > left)
1089 {
1090 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001091 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -07001092 eid,elem_len,left);
1093 return NULL;
1094 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301095 if (elem_id == eid)
Jeff Johnson295189b2012-06-20 16:38:30 -07001096 {
1097 return ptr;
1098 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301099
Jeff Johnson295189b2012-06-20 16:38:30 -07001100 left -= elem_len;
1101 ptr += (elem_len + 2);
1102 }
1103 return NULL;
1104}
1105
Jeff Johnson295189b2012-06-20 16:38:30 -07001106/* Check if rate is 11g rate or not */
1107static int wlan_hdd_rate_is_11g(u8 rate)
1108{
Sanjay Devnani28322e22013-06-21 16:13:40 -07001109 static const u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 108}; /* actual rate * 2 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001110 u8 i;
1111 for (i = 0; i < 8; i++)
1112 {
1113 if(rate == gRateArray[i])
1114 return TRUE;
1115 }
1116 return FALSE;
1117}
1118
1119/* Check for 11g rate and set proper 11g only mode */
1120static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
1121 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
1122{
1123 u8 i, num_rates = pIe[0];
1124
1125 pIe += 1;
1126 for ( i = 0; i < num_rates; i++)
1127 {
1128 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
1129 {
1130 /* If rate set have 11g rate than change the mode to 11G */
1131 *pSapHw_mode = eSAP_DOT11_MODE_11g;
1132 if (pIe[i] & BASIC_RATE_MASK)
1133 {
1134 /* If we have 11g rate as basic rate, it means mode
1135 is 11g only mode.
1136 */
1137 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
1138 *pCheckRatesfor11g = FALSE;
1139 }
1140 }
1141 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
1142 {
1143 *require_ht = TRUE;
1144 }
1145 }
1146 return;
1147}
1148
1149static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
1150{
1151 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1152 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1153 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1154 u8 checkRatesfor11g = TRUE;
1155 u8 require_ht = FALSE;
1156 u8 *pIe=NULL;
1157
1158 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
1159
1160 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
1161 pBeacon->head_len, WLAN_EID_SUPP_RATES);
1162 if (pIe != NULL)
1163 {
1164 pIe += 1;
1165 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1166 &pConfig->SapHw_mode);
1167 }
1168
1169 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1170 WLAN_EID_EXT_SUPP_RATES);
1171 if (pIe != NULL)
1172 {
1173
1174 pIe += 1;
1175 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1176 &pConfig->SapHw_mode);
1177 }
1178
1179 if( pConfig->channel > 14 )
1180 {
1181 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
1182 }
1183
1184 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1185 WLAN_EID_HT_CAPABILITY);
1186
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301187 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001188 {
1189 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
1190 if(require_ht)
1191 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
1192 }
1193}
1194
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301195static int wlan_hdd_add_ie(hdd_adapter_t* pHostapdAdapter, v_U8_t *genie,
1196 v_U8_t *total_ielen, v_U8_t *oui, v_U8_t oui_size)
1197{
Arif Hussaine7f3ea52013-09-12 21:56:36 -07001198 v_U16_t ielen = 0;
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301199 v_U8_t *pIe = NULL;
1200 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1201
1202 pIe = wlan_hdd_get_vendor_oui_ie_ptr(oui, oui_size,
1203 pBeacon->tail, pBeacon->tail_len);
1204
1205 if (pIe)
1206 {
1207 ielen = pIe[1] + 2;
1208 if ((*total_ielen + ielen) <= MAX_GENIE_LEN)
1209 {
1210 vos_mem_copy(&genie[*total_ielen], pIe, ielen);
1211 }
1212 else
1213 {
1214 hddLog( VOS_TRACE_LEVEL_ERROR, "**Ie Length is too big***");
1215 return -EINVAL;
1216 }
1217 *total_ielen += ielen;
1218 }
1219 return 0;
1220}
1221
Arif Hussaine7f3ea52013-09-12 21:56:36 -07001222static void wlan_hdd_add_hostapd_conf_vsie(hdd_adapter_t* pHostapdAdapter,
1223 v_U8_t *genie, v_U8_t *total_ielen)
1224{
1225 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1226 int left = pBeacon->tail_len;
1227 v_U8_t *ptr = pBeacon->tail;
1228 v_U8_t elem_id, elem_len;
1229 v_U16_t ielen = 0;
1230
1231 if ( NULL == ptr || 0 == left )
1232 return;
1233
1234 while (left >= 2)
1235 {
1236 elem_id = ptr[0];
1237 elem_len = ptr[1];
1238 left -= 2;
1239 if (elem_len > left)
1240 {
1241 hddLog( VOS_TRACE_LEVEL_ERROR,
1242 "****Invalid IEs eid = %d elem_len=%d left=%d*****",
1243 elem_id, elem_len, left);
1244 return;
1245 }
1246 if (IE_EID_VENDOR == elem_id)
1247 {
1248 /* skipping the VSIE's which we don't want to include or
1249 * it will be included by existing code
1250 */
1251 if ((memcmp( &ptr[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) != 0 ) &&
1252#ifdef WLAN_FEATURE_WFD
1253 (memcmp( &ptr[2], WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE) != 0) &&
1254#endif
1255 (memcmp( &ptr[2], WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) &&
1256 (memcmp( &ptr[2], BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) &&
1257 (memcmp( &ptr[2], "\x00\x50\xf2\x02", WPA_OUI_TYPE_SIZE) != 0) &&
1258 (memcmp( &ptr[2], WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) &&
1259 (memcmp( &ptr[2], P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE) != 0))
1260 {
1261 ielen = ptr[1] + 2;
1262 if ((*total_ielen + ielen) <= MAX_GENIE_LEN)
1263 {
1264 vos_mem_copy(&genie[*total_ielen], ptr, ielen);
1265 *total_ielen += ielen;
1266 }
1267 else
1268 {
1269 hddLog( VOS_TRACE_LEVEL_ERROR,
1270 "IE Length is too big "
1271 "IEs eid=%d elem_len=%d total_ie_lent=%d",
1272 elem_id, elem_len, *total_ielen);
1273 }
1274 }
1275 }
1276
1277 left -= elem_len;
1278 ptr += (elem_len + 2);
1279 }
1280 return;
1281}
1282
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001283#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001284static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1285 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001286#else
1287static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1288 struct cfg80211_beacon_data *params)
1289#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001290{
1291 v_U8_t *genie;
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301292 v_U8_t total_ielen = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001293 v_U8_t addIE[1] = {0};
Jeff Johnsone7245742012-09-05 17:12:55 -07001294 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001295
1296 genie = vos_mem_malloc(MAX_GENIE_LEN);
1297
1298 if(genie == NULL) {
1299
1300 return -ENOMEM;
1301 }
1302
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301303 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1304 &total_ielen, WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001305 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301306 ret = -EINVAL;
1307 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001308 }
1309
1310#ifdef WLAN_FEATURE_WFD
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301311 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1312 &total_ielen, WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE))
1313 {
1314 ret = -EINVAL;
1315 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001316 }
1317#endif
1318
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301319 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1320 &total_ielen, P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001321 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301322 ret = -EINVAL;
1323 goto done;
1324 }
1325
1326 if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode)
1327 {
Arif Hussaine7f3ea52013-09-12 21:56:36 -07001328 wlan_hdd_add_hostapd_conf_vsie(pHostapdAdapter, genie, &total_ielen);
Jeff Johnson295189b2012-06-20 16:38:30 -07001329 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001330
1331 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1332 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1333 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1334 {
1335 hddLog(LOGE,
1336 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001337 ret = -EINVAL;
1338 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001339 }
1340
1341 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1342 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1343 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1344 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1345 ==eHAL_STATUS_FAILURE)
1346 {
1347 hddLog(LOGE,
1348 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001349 ret = -EINVAL;
1350 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001351 }
1352
1353 // Added for ProResp IE
1354 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1355 {
1356 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1357 u8 probe_rsp_ie_len[3] = {0};
1358 u8 counter = 0;
1359 /* Check Probe Resp Length if it is greater then 255 then Store
1360 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1361 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1362 Store More then 255 bytes into One Variable.
1363 */
1364 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1365 {
1366 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1367 {
1368 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1369 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1370 }
1371 else
1372 {
1373 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1374 rem_probe_resp_ie_len = 0;
1375 }
1376 }
1377
1378 rem_probe_resp_ie_len = 0;
1379
1380 if (probe_rsp_ie_len[0] > 0)
1381 {
1382 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1383 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1384 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1385 probe_rsp_ie_len[0], NULL,
1386 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1387 {
1388 hddLog(LOGE,
1389 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001390 ret = -EINVAL;
1391 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001392 }
1393 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1394 }
1395
1396 if (probe_rsp_ie_len[1] > 0)
1397 {
1398 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1399 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1400 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1401 probe_rsp_ie_len[1], NULL,
1402 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1403 {
1404 hddLog(LOGE,
1405 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001406 ret = -EINVAL;
1407 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001408 }
1409 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1410 }
1411
1412 if (probe_rsp_ie_len[2] > 0)
1413 {
1414 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1415 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1416 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1417 probe_rsp_ie_len[2], NULL,
1418 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1419 {
1420 hddLog(LOGE,
1421 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001422 ret = -EINVAL;
1423 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001424 }
1425 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1426 }
1427
1428 if (probe_rsp_ie_len[1] == 0 )
1429 {
1430 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1431 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1432 eANI_BOOLEAN_FALSE) )
1433 {
1434 hddLog(LOGE,
1435 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1436 }
1437 }
1438
1439 if (probe_rsp_ie_len[2] == 0 )
1440 {
1441 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1442 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1443 eANI_BOOLEAN_FALSE) )
1444 {
1445 hddLog(LOGE,
1446 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1447 }
1448 }
1449
1450 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1451 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1452 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1453 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1454 == eHAL_STATUS_FAILURE)
1455 {
1456 hddLog(LOGE,
1457 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001458 ret = -EINVAL;
1459 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001460 }
1461 }
1462 else
1463 {
1464 // Reset WNI_CFG_PROBE_RSP Flags
1465 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1466
1467 hddLog(VOS_TRACE_LEVEL_INFO,
1468 "%s: No Probe Response IE received in set beacon",
1469 __func__);
1470 }
1471
1472 // Added for AssocResp IE
1473 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1474 {
1475 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1476 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1477 params->assocresp_ies_len, NULL,
1478 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1479 {
1480 hddLog(LOGE,
1481 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001482 ret = -EINVAL;
1483 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001484 }
1485
1486 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1487 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1488 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1489 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1490 == eHAL_STATUS_FAILURE)
1491 {
1492 hddLog(LOGE,
1493 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001494 ret = -EINVAL;
1495 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001496 }
1497 }
1498 else
1499 {
1500 hddLog(VOS_TRACE_LEVEL_INFO,
1501 "%s: No Assoc Response IE received in set beacon",
1502 __func__);
1503
1504 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1505 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1506 eANI_BOOLEAN_FALSE) )
1507 {
1508 hddLog(LOGE,
1509 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1510 }
1511 }
1512
Jeff Johnsone7245742012-09-05 17:12:55 -07001513done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001514 vos_mem_free(genie);
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301515 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07001516}
Jeff Johnson295189b2012-06-20 16:38:30 -07001517
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301518/*
Jeff Johnson295189b2012-06-20 16:38:30 -07001519 * FUNCTION: wlan_hdd_validate_operation_channel
1520 * called by wlan_hdd_cfg80211_start_bss() and
1521 * wlan_hdd_cfg80211_set_channel()
1522 * This function validates whether given channel is part of valid
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301523 * channel list.
1524 */
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001525VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001526{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301527
Jeff Johnson295189b2012-06-20 16:38:30 -07001528 v_U32_t num_ch = 0;
1529 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1530 u32 indx = 0;
1531 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301532 v_U8_t fValidChannel = FALSE, count = 0;
1533 hdd_config_t *hdd_pConfig_ini= (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301534
Jeff Johnson295189b2012-06-20 16:38:30 -07001535 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1536
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301537 if ( hdd_pConfig_ini->sapAllowAllChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001538 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301539 /* Validate the channel */
1540 for (count = RF_CHAN_1 ; count <= RF_CHAN_165 ; count++)
Jeff Johnson295189b2012-06-20 16:38:30 -07001541 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301542 if ( channel == rfChannels[count].channelNum )
1543 {
1544 fValidChannel = TRUE;
1545 break;
1546 }
1547 }
1548 if (fValidChannel != TRUE)
1549 {
1550 hddLog(VOS_TRACE_LEVEL_ERROR,
1551 "%s: Invalid Channel [%d]", __func__, channel);
1552 return VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001553 }
1554 }
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301555 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001556 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301557 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1558 valid_ch, &num_ch))
1559 {
1560 hddLog(VOS_TRACE_LEVEL_ERROR,
1561 "%s: failed to get valid channel list", __func__);
1562 return VOS_STATUS_E_FAILURE;
1563 }
1564 for (indx = 0; indx < num_ch; indx++)
1565 {
1566 if (channel == valid_ch[indx])
1567 {
1568 break;
1569 }
1570 }
1571
1572 if (indx >= num_ch)
1573 {
1574 hddLog(VOS_TRACE_LEVEL_ERROR,
1575 "%s: Invalid Channel [%d]", __func__, channel);
1576 return VOS_STATUS_E_FAILURE;
1577 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001578 }
1579 return VOS_STATUS_SUCCESS;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301580
Jeff Johnson295189b2012-06-20 16:38:30 -07001581}
1582
Viral Modi3a32cc52013-02-08 11:14:52 -08001583/**
1584 * FUNCTION: wlan_hdd_cfg80211_set_channel
1585 * This function is used to set the channel number
1586 */
1587static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
1588 struct ieee80211_channel *chan,
1589 enum nl80211_channel_type channel_type
1590 )
1591{
1592 v_U32_t num_ch = 0;
Jeff Johnson4416a782013-03-25 14:17:50 -07001593 int channel = 0;
Viral Modi3a32cc52013-02-08 11:14:52 -08001594 hdd_adapter_t *pAdapter = NULL;
1595 int freq = chan->center_freq; /* freq is in MHZ */
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301596 hdd_context_t *pHddCtx;
1597 int status;
Viral Modi3a32cc52013-02-08 11:14:52 -08001598
1599 ENTER();
1600
1601 if( NULL == dev )
1602 {
1603 hddLog(VOS_TRACE_LEVEL_ERROR,
1604 "%s: Called with dev = NULL.\n", __func__);
1605 return -ENODEV;
1606 }
1607 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1608
1609 hddLog(VOS_TRACE_LEVEL_INFO,
1610 "%s: device_mode = %d freq = %d \n",__func__,
1611 pAdapter->device_mode, chan->center_freq);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301612
1613 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1614 status = wlan_hdd_validate_context(pHddCtx);
1615
1616 if (0 != status)
Viral Modi3a32cc52013-02-08 11:14:52 -08001617 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301618 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1619 "%s: HDD context is not valid", __func__);
1620 return status;
Viral Modi3a32cc52013-02-08 11:14:52 -08001621 }
1622
1623 /*
1624 * Do freq to chan conversion
1625 * TODO: for 11a
1626 */
1627
1628 channel = ieee80211_frequency_to_channel(freq);
1629
1630 /* Check freq range */
1631 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
1632 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
1633 {
1634 hddLog(VOS_TRACE_LEVEL_ERROR,
1635 "%s: Channel [%d] is outside valid range from %d to %d\n",
1636 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
1637 WNI_CFG_CURRENT_CHANNEL_STAMAX);
1638 return -EINVAL;
1639 }
1640
1641 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1642
Gopichand Nakkala6ab19562013-03-07 13:59:42 +05301643 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode) &&
1644 (WLAN_HDD_P2P_GO != pAdapter->device_mode))
Viral Modi3a32cc52013-02-08 11:14:52 -08001645 {
1646 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
1647 {
1648 hddLog(VOS_TRACE_LEVEL_ERROR,
1649 "%s: Invalid Channel [%d] \n", __func__, channel);
1650 return -EINVAL;
1651 }
1652 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1653 "%s: set channel to [%d] for device mode =%d",
1654 __func__, channel,pAdapter->device_mode);
1655 }
1656 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Viral Modi3a32cc52013-02-08 11:14:52 -08001657 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Viral Modi3a32cc52013-02-08 11:14:52 -08001658 )
1659 {
1660 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
1661 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
1662 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1663
1664 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
1665 {
1666 /* Link is up then return cant set channel*/
1667 hddLog( VOS_TRACE_LEVEL_ERROR,
1668 "%s: IBSS Associated, can't set the channel\n", __func__);
1669 return -EINVAL;
1670 }
1671
1672 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
1673 pHddStaCtx->conn_info.operationChannel = channel;
1674 pRoamProfile->ChannelInfo.ChannelList =
1675 &pHddStaCtx->conn_info.operationChannel;
1676 }
1677 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Viral Modi3a32cc52013-02-08 11:14:52 -08001678 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Viral Modi3a32cc52013-02-08 11:14:52 -08001679 )
1680 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301681 if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
1682 {
1683 if(VOS_STATUS_SUCCESS !=
1684 wlan_hdd_validate_operation_channel(pAdapter,channel))
1685 {
1686 hddLog(VOS_TRACE_LEVEL_ERROR,
1687 "%s: Invalid Channel [%d] \n", __func__, channel);
1688 return -EINVAL;
1689 }
1690 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1691 }
1692 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
Viral Modi3a32cc52013-02-08 11:14:52 -08001693 {
1694 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
1695
1696 /* If auto channel selection is configured as enable/ 1 then ignore
1697 channel set by supplicant
1698 */
1699 if ( cfg_param->apAutoChannelSelection )
1700 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301701 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel =
1702 AUTO_CHANNEL_SELECT;
Viral Modi3a32cc52013-02-08 11:14:52 -08001703 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1704 "%s: set channel to auto channel (0) for device mode =%d",
1705 __func__, pAdapter->device_mode);
1706 }
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301707 else
1708 {
1709 if(VOS_STATUS_SUCCESS !=
1710 wlan_hdd_validate_operation_channel(pAdapter,channel))
1711 {
1712 hddLog(VOS_TRACE_LEVEL_ERROR,
1713 "%s: Invalid Channel [%d] \n", __func__, channel);
1714 return -EINVAL;
1715 }
1716 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1717 }
Viral Modi3a32cc52013-02-08 11:14:52 -08001718 }
1719 }
1720 else
1721 {
1722 hddLog(VOS_TRACE_LEVEL_FATAL,
1723 "%s: Invalid device mode failed to set valid channel", __func__);
1724 return -EINVAL;
1725 }
1726 EXIT();
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301727 return status;
Viral Modi3a32cc52013-02-08 11:14:52 -08001728}
1729
Jeff Johnson295189b2012-06-20 16:38:30 -07001730#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1731static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1732 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001733#else
1734static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1735 struct cfg80211_beacon_data *params,
1736 const u8 *ssid, size_t ssid_len,
1737 enum nl80211_hidden_ssid hidden_ssid)
1738#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001739{
1740 tsap_Config_t *pConfig;
1741 beacon_data_t *pBeacon = NULL;
1742 struct ieee80211_mgmt *pMgmt_frame;
1743 v_U8_t *pIe=NULL;
1744 v_U16_t capab_info;
1745 eCsrAuthType RSNAuthType;
1746 eCsrEncryptionType RSNEncryptType;
1747 eCsrEncryptionType mcRSNEncryptType;
1748 int status = VOS_STATUS_SUCCESS;
1749 tpWLAN_SAPEventCB pSapEventCallback;
1750 hdd_hostapd_state_t *pHostapdState;
1751 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1752 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301753 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001754 struct qc_mac_acl_entry *acl_entry = NULL;
1755 v_SINT_t i;
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001756 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001757
1758 ENTER();
1759
1760 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1761
1762 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1763
1764 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1765
1766 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1767
1768 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1769
1770 //channel is already set in the set_channel Call back
1771 //pConfig->channel = pCommitConfig->channel;
1772
1773 /*Protection parameter to enable or disable*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301774 pConfig->protEnabled =
Jeff Johnson295189b2012-06-20 16:38:30 -07001775 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1776
1777 pConfig->dtim_period = pBeacon->dtim_period;
1778
1779 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1780 pConfig->dtim_period);
1781
1782
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001783 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001784 {
1785 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001786 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001787 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001788 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001789 tANI_BOOLEAN restartNeeded;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001790 pConfig->ieee80211d = 1;
1791 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1792 sme_setRegInfo(hHal, pConfig->countryCode);
1793 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
Jeff Johnson295189b2012-06-20 16:38:30 -07001794 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001795 else
1796 {
1797 pConfig->ieee80211d = 0;
1798 }
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301799 /*
1800 * If auto channel is configured i.e. channel is 0,
1801 * so skip channel validation.
1802 */
1803 if( AUTO_CHANNEL_SELECT != pConfig->channel )
1804 {
1805 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1806 {
1807 hddLog(VOS_TRACE_LEVEL_ERROR,
1808 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1809 return -EINVAL;
1810 }
1811 }
1812 else
1813 {
1814 if(1 != pHddCtx->is_dynamic_channel_range_set)
1815 {
1816 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
1817 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
1818 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
1819 }
1820 pHddCtx->is_dynamic_channel_range_set = 0;
1821 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001822 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001823 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001824 {
1825 pConfig->ieee80211d = 0;
1826 }
1827 pConfig->authType = eSAP_AUTO_SWITCH;
1828
1829 capab_info = pMgmt_frame->u.beacon.capab_info;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301830
1831 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
Jeff Johnson295189b2012-06-20 16:38:30 -07001832 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1833
1834 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1835
1836 /*Set wps station to configured*/
1837 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1838
1839 if(pIe)
1840 {
1841 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1842 {
1843 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1844 return -EINVAL;
1845 }
1846 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1847 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001848 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001849 /* Check 15 bit of WPS IE as it contain information for wps state
1850 * WPS state
1851 */
1852 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1853 {
1854 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1855 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1856 {
1857 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1858 }
1859 }
1860 }
1861 else
1862 {
1863 pConfig->wps_state = SAP_WPS_DISABLED;
1864 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301865 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
Jeff Johnson295189b2012-06-20 16:38:30 -07001866
1867 pConfig->RSNWPAReqIELength = 0;
1868 pConfig->pRSNWPAReqIE = NULL;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301869 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001870 WLAN_EID_RSN);
1871 if(pIe && pIe[1])
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301872 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001873 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1874 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1875 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301876 /* The actual processing may eventually be more extensive than
1877 * this. Right now, just consume any PMKIDs that are sent in
Jeff Johnson295189b2012-06-20 16:38:30 -07001878 * by the app.
1879 * */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301880 status = hdd_softap_unpackIE(
Jeff Johnson295189b2012-06-20 16:38:30 -07001881 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1882 &RSNEncryptType,
1883 &mcRSNEncryptType,
1884 &RSNAuthType,
1885 pConfig->pRSNWPAReqIE[1]+2,
1886 pConfig->pRSNWPAReqIE );
1887
1888 if( VOS_STATUS_SUCCESS == status )
1889 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301890 /* Now copy over all the security attributes you have
1891 * parsed out
Jeff Johnson295189b2012-06-20 16:38:30 -07001892 * */
1893 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1894 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1895 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1896 = RSNEncryptType;
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05301897 hddLog( LOG1, FL("CSR AuthType = %d, "
Jeff Johnson295189b2012-06-20 16:38:30 -07001898 "EncryptionType = %d mcEncryptionType = %d\n"),
1899 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1900 }
1901 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301902
Jeff Johnson295189b2012-06-20 16:38:30 -07001903 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1904 pBeacon->tail, pBeacon->tail_len);
1905
1906 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1907 {
1908 if (pConfig->pRSNWPAReqIE)
1909 {
1910 /*Mixed mode WPA/WPA2*/
1911 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1912 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1913 }
1914 else
1915 {
1916 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1917 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1918 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301919 status = hdd_softap_unpackIE(
Jeff Johnson295189b2012-06-20 16:38:30 -07001920 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1921 &RSNEncryptType,
1922 &mcRSNEncryptType,
1923 &RSNAuthType,
1924 pConfig->pRSNWPAReqIE[1]+2,
1925 pConfig->pRSNWPAReqIE );
1926
1927 if( VOS_STATUS_SUCCESS == status )
1928 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301929 /* Now copy over all the security attributes you have
1930 * parsed out
Jeff Johnson295189b2012-06-20 16:38:30 -07001931 * */
1932 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1933 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1934 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1935 = RSNEncryptType;
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05301936 hddLog( LOG1, FL("CSR AuthType = %d, "
Jeff Johnson295189b2012-06-20 16:38:30 -07001937 "EncryptionType = %d mcEncryptionType = %d\n"),
1938 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1939 }
1940 }
1941 }
1942
Jeff Johnson4416a782013-03-25 14:17:50 -07001943 if (pConfig->RSNWPAReqIELength > sizeof wpaRsnIEdata) {
1944 hddLog( VOS_TRACE_LEVEL_ERROR, "**RSNWPAReqIELength is too large***");
1945 return -EINVAL;
1946 }
1947
Jeff Johnson295189b2012-06-20 16:38:30 -07001948 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1949
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001950#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001951 if (params->ssid != NULL)
1952 {
1953 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1954 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1955 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1956 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1957 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001958#else
1959 if (ssid != NULL)
1960 {
1961 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1962 pConfig->SSIDinfo.ssid.length = ssid_len;
1963 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1964 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1965 }
1966#endif
1967
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301968 vos_mem_copy(pConfig->self_macaddr.bytes,
Jeff Johnson295189b2012-06-20 16:38:30 -07001969 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301970
Jeff Johnson295189b2012-06-20 16:38:30 -07001971 /* default value */
1972 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1973 pConfig->num_accept_mac = 0;
1974 pConfig->num_deny_mac = 0;
1975
1976 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1977 pBeacon->tail, pBeacon->tail_len);
1978
1979 /* pIe for black list is following form:
1980 type : 1 byte
1981 length : 1 byte
1982 OUI : 4 bytes
1983 acl type : 1 byte
1984 no of mac addr in black list: 1 byte
1985 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301986 */
1987 if ((pIe != NULL) && (pIe[1] != 0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001988 {
1989 pConfig->SapMacaddr_acl = pIe[6];
1990 pConfig->num_deny_mac = pIe[7];
1991 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1992 pIe[6], pIe[7]);
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05301993 if (pConfig->num_deny_mac > MAX_ACL_MAC_ADDRESS)
1994 pConfig->num_deny_mac = MAX_ACL_MAC_ADDRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07001995 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1996 for (i = 0; i < pConfig->num_deny_mac; i++)
1997 {
1998 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1999 acl_entry++;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302000 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002001 }
2002 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
2003 pBeacon->tail, pBeacon->tail_len);
2004
2005 /* pIe for white list is following form:
2006 type : 1 byte
2007 length : 1 byte
2008 OUI : 4 bytes
2009 acl type : 1 byte
2010 no of mac addr in white list: 1 byte
2011 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302012 */
2013 if ((pIe != NULL) && (pIe[1] != 0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002014 {
2015 pConfig->SapMacaddr_acl = pIe[6];
2016 pConfig->num_accept_mac = pIe[7];
2017 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
2018 pIe[6], pIe[7]);
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05302019 if (pConfig->num_accept_mac > MAX_ACL_MAC_ADDRESS)
2020 pConfig->num_accept_mac = MAX_ACL_MAC_ADDRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07002021 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
2022 for (i = 0; i < pConfig->num_accept_mac; i++)
2023 {
2024 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
2025 acl_entry++;
2026 }
2027 }
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05302028
Jeff Johnson295189b2012-06-20 16:38:30 -07002029 wlan_hdd_set_sapHwmode(pHostapdAdapter);
2030
Jeff Johnsone7245742012-09-05 17:12:55 -07002031#ifdef WLAN_FEATURE_11AC
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08002032 /* Overwrite the hostapd setting for HW mode only for 11ac.
2033 * This is valid only if mode is set to 11n in hostapd and either AUTO or 11ac in .ini .
2034 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode) */
2035 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
2036 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302037 (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08002038 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
2039 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07002040 {
2041 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
Ravi Joshi83bfaa12013-05-28 22:12:08 -07002042
2043 /* Disable VHT support in 2.4 GHz band */
2044 if (pConfig->channel <= 14 &&
2045 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->enableVhtFor24GHzBand == FALSE)
2046 {
2047 pConfig->SapHw_mode = eSAP_DOT11_MODE_11n;
2048 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002049 }
2050#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302051
Ravi Joshiaeb7d9e2013-05-02 12:28:14 -07002052 if ( AUTO_CHANNEL_SELECT != pConfig->channel )
2053 {
2054 sme_SelectCBMode(hHal,
2055 sapConvertSapPhyModeToCsrPhyMode(pConfig->SapHw_mode),
2056 pConfig->channel);
2057 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002058 // ht_capab is not what the name conveys,this is used for protection bitmap
2059 pConfig->ht_capab =
2060 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
2061
2062 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
2063 {
2064 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
2065 return -EINVAL;
2066 }
2067
2068 //Uapsd Enabled Bit
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302069 pConfig->UapsdEnable =
Jeff Johnson295189b2012-06-20 16:38:30 -07002070 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
2071 //Enable OBSS protection
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302072 pConfig->obssProtEnabled =
2073 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
Jeff Johnson295189b2012-06-20 16:38:30 -07002074
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302075 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
Jeff Johnson295189b2012-06-20 16:38:30 -07002076 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302077 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
Jeff Johnson295189b2012-06-20 16:38:30 -07002078 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
2079 (int)pConfig->channel);
2080 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302081 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
2082 pConfig->authType);
Jeff Johnson295189b2012-06-20 16:38:30 -07002083 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302084 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
Jeff Johnson295189b2012-06-20 16:38:30 -07002085 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
2086 pConfig->protEnabled, pConfig->obssProtEnabled);
2087
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302088 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07002089 {
2090 //Bss already started. just return.
2091 //TODO Probably it should update some beacon params.
2092 hddLog( LOGE, "Bss Already started...Ignore the request");
2093 EXIT();
2094 return 0;
2095 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302096
Jeff Johnson295189b2012-06-20 16:38:30 -07002097 pConfig->persona = pHostapdAdapter->device_mode;
2098
2099 pSapEventCallback = hdd_hostapd_SAPEventCB;
2100 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
2101 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
2102 {
2103 hddLog(LOGE,FL("SAP Start Bss fail\n"));
2104 return -EINVAL;
2105 }
2106
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302107 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07002108 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
2109
2110 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302111
Jeff Johnson295189b2012-06-20 16:38:30 -07002112 if (!VOS_IS_STATUS_SUCCESS(status))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302113 {
2114 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07002115 ("ERROR: HDD vos wait for single_event failed!!\n"));
2116 VOS_ASSERT(0);
2117 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302118
Jeff Johnson295189b2012-06-20 16:38:30 -07002119 //Succesfully started Bss update the state bit.
2120 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
2121
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002122#ifdef WLAN_FEATURE_P2P_DEBUG
2123 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
2124 {
2125 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
2126 {
2127 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
2128 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002129 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002130 }
2131 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
2132 {
2133 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
2134 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002135 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002136 }
2137 }
2138#endif
2139
Jeff Johnson295189b2012-06-20 16:38:30 -07002140 pHostapdState->bCommit = TRUE;
2141 EXIT();
2142
2143 return 0;
2144}
2145
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002146#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302147static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
2148 struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -07002149 struct beacon_parameters *params)
2150{
2151 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302152 hdd_context_t *pHddCtx;
2153 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002154
2155 ENTER();
2156
2157 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
2158
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302159 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2160 status = wlan_hdd_validate_context(pHddCtx);
2161
2162 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002163 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302164 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2165 "%s: HDD context is not valid", __func__);
2166 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002167 }
2168
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302169 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002170 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002171 )
2172 {
2173 beacon_data_t *old,*new;
2174
2175 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302176
Jeff Johnson295189b2012-06-20 16:38:30 -07002177 if (old)
2178 return -EALREADY;
2179
2180 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2181
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302182 if(status != VOS_STATUS_SUCCESS)
Jeff Johnson295189b2012-06-20 16:38:30 -07002183 {
2184 hddLog(VOS_TRACE_LEVEL_FATAL,
2185 "%s:Error!!! Allocating the new beacon\n",__func__);
2186 return -EINVAL;
2187 }
2188
2189 pAdapter->sessionCtx.ap.beacon = new;
2190
2191 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2192 }
2193
2194 EXIT();
2195 return status;
2196}
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302197
2198static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07002199 struct net_device *dev,
2200 struct beacon_parameters *params)
2201{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302202 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302203 hdd_context_t *pHddCtx;
2204 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002205
2206 ENTER();
2207
2208 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2209 __func__,pAdapter->device_mode);
2210
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302211 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2212 status = wlan_hdd_validate_context(pHddCtx);
2213
2214 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002215 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302216 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2217 "%s: HDD context is not valid", __func__);
2218 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002219 }
2220
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302221 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002222 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302223 )
Jeff Johnson295189b2012-06-20 16:38:30 -07002224 {
2225 beacon_data_t *old,*new;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302226
Jeff Johnson295189b2012-06-20 16:38:30 -07002227 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302228
Jeff Johnson295189b2012-06-20 16:38:30 -07002229 if (!old)
2230 return -ENOENT;
2231
2232 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2233
2234 if(status != VOS_STATUS_SUCCESS) {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302235 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -07002236 "%s: Error!!! Allocating the new beacon\n",__func__);
2237 return -EINVAL;
2238 }
2239
2240 pAdapter->sessionCtx.ap.beacon = new;
2241
2242 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2243 }
2244
2245 EXIT();
2246 return status;
2247}
2248
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002249#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
2250
2251#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002252static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
2253 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002254#else
2255static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
2256 struct net_device *dev)
2257#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002258{
2259 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07002260 hdd_context_t *pHddCtx = NULL;
2261 hdd_scaninfo_t *pScanInfo = NULL;
2262 hdd_adapter_t *staAdapter = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302263 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002264
2265 ENTER();
2266
2267 if (NULL == pAdapter)
2268 {
2269 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002270 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002271 return -ENODEV;
2272 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002273
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302274 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2275 status = wlan_hdd_validate_context(pHddCtx);
2276
2277 if (0 != status)
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002278 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302279 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2280 "%s: HDD context is not valid", __func__);
2281 return status;
Jeff Johnson4416a782013-03-25 14:17:50 -07002282 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002283
2284 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
2285 if (NULL == staAdapter)
2286 {
2287 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
2288 if (NULL == staAdapter)
2289 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302290 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002291 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002292 return -ENODEV;
2293 }
2294 }
2295
2296 pScanInfo = &pHddCtx->scan_info;
2297
Jeff Johnson295189b2012-06-20 16:38:30 -07002298 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2299 __func__,pAdapter->device_mode);
2300
Jeff Johnsone7245742012-09-05 17:12:55 -07002301 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
2302 {
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002303 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05302304 hdd_abort_mac_scan(staAdapter->pHddCtx, pAdapter->sessionId);
Jeff Johnsone7245742012-09-05 17:12:55 -07002305 status = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002306 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07002307 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
2308 if (!status)
2309 {
2310 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson902c9832012-12-10 14:28:09 -08002311 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002312 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07002313 VOS_ASSERT(pScanInfo->mScanPending);
2314 return 0;
2315 }
2316 }
2317
Jeff Johnson295189b2012-06-20 16:38:30 -07002318 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002319 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002320 )
2321 {
2322 beacon_data_t *old;
2323
2324 old = pAdapter->sessionCtx.ap.beacon;
2325
2326 if (!old)
2327 return -ENOENT;
2328
Jeff Johnson295189b2012-06-20 16:38:30 -07002329 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002330
2331 mutex_lock(&pHddCtx->sap_lock);
2332 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2333 {
Jeff Johnson4416a782013-03-25 14:17:50 -07002334 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss(pHddCtx->pvosContext) ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07002335 {
2336 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2337
2338 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2339
2340 if (!VOS_IS_STATUS_SUCCESS(status))
2341 {
2342 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2343 ("ERROR: HDD vos wait for single_event failed!!\n"));
2344 VOS_ASSERT(0);
2345 }
2346 }
2347 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2348 }
2349 mutex_unlock(&pHddCtx->sap_lock);
2350
2351 if(status != VOS_STATUS_SUCCESS)
2352 {
2353 hddLog(VOS_TRACE_LEVEL_FATAL,
2354 "%s:Error!!! Stopping the BSS\n",__func__);
2355 return -EINVAL;
2356 }
2357
Jeff Johnson4416a782013-03-25 14:17:50 -07002358 if (ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002359 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
2360 ==eHAL_STATUS_FAILURE)
2361 {
2362 hddLog(LOGE,
2363 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
2364 }
2365
Jeff Johnson4416a782013-03-25 14:17:50 -07002366 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002367 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2368 eANI_BOOLEAN_FALSE) )
2369 {
2370 hddLog(LOGE,
2371 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
2372 }
2373
2374 // Reset WNI_CFG_PROBE_RSP Flags
2375 wlan_hdd_reset_prob_rspies(pAdapter);
2376
2377 pAdapter->sessionCtx.ap.beacon = NULL;
2378 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002379#ifdef WLAN_FEATURE_P2P_DEBUG
2380 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
2381 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
2382 {
2383 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
2384 "GO got removed");
2385 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
2386 }
2387#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002388 }
2389 EXIT();
2390 return status;
2391}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002392
2393#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2394
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302395static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2396 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002397 struct cfg80211_ap_settings *params)
2398{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302399 hdd_adapter_t *pAdapter;
2400 hdd_context_t *pHddCtx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302401 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002402
2403 ENTER();
2404
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302405 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002406 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302407 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302408 "%s: Device is Null", __func__);
2409 return -ENODEV;
2410 }
2411
2412 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2413 if (NULL == pAdapter)
2414 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302415 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302416 "%s: HDD adapter is Null", __func__);
2417 return -ENODEV;
2418 }
2419
2420 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2421 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302422 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302423 "%s: HDD adapter magic is invalid", __func__);
2424 return -ENODEV;
2425 }
2426
2427 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302428 status = wlan_hdd_validate_context(pHddCtx);
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302429
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302430 if (0 != status)
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302431 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302432 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2433 "%s: HDD context is not valid", __func__);
2434 return status;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302435 }
2436
2437 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2438 __func__, pAdapter->device_mode);
2439
2440 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002441 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002442 )
2443 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302444 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002445
2446 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302447
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002448 if (old)
2449 return -EALREADY;
2450
2451 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2452
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302453 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002454 {
2455 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302456 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002457 return -EINVAL;
2458 }
2459 pAdapter->sessionCtx.ap.beacon = new;
Viral Modi3a32cc52013-02-08 11:14:52 -08002460#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Yue Maf49ba872013-08-19 12:04:25 -07002461 wlan_hdd_cfg80211_set_channel(wiphy, dev,
2462#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2463 params->channel, params->channel_type);
2464#else
2465 params->chandef.chan, cfg80211_get_chandef_type(&(params->chandef)));
2466#endif
Viral Modi3a32cc52013-02-08 11:14:52 -08002467#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002468 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2469 params->ssid_len, params->hidden_ssid);
2470 }
2471
2472 EXIT();
2473 return status;
2474}
2475
2476
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302477static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002478 struct net_device *dev,
2479 struct cfg80211_beacon_data *params)
2480{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302481 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302482 hdd_context_t *pHddCtx;
2483 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002484
2485 ENTER();
2486
2487 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2488 __func__, pAdapter->device_mode);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302489
2490 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2491 status = wlan_hdd_validate_context(pHddCtx);
2492
2493 if (0 != status)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002494 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302495 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2496 "%s: HDD context is not valid", __func__);
2497 return status;
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002498 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002499
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302500 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002501 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302502 )
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002503 {
2504 beacon_data_t *old,*new;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302505
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002506 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302507
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002508 if (!old)
2509 return -ENOENT;
2510
2511 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2512
2513 if(status != VOS_STATUS_SUCCESS) {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302514 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002515 "%s: Error!!! Allocating the new beacon\n",__func__);
2516 return -EINVAL;
2517 }
2518
2519 pAdapter->sessionCtx.ap.beacon = new;
2520
2521 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2522 }
2523
2524 EXIT();
2525 return status;
2526}
2527
2528#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2529
Jeff Johnson295189b2012-06-20 16:38:30 -07002530
2531static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2532 struct net_device *dev,
2533 struct bss_parameters *params)
2534{
2535 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2536
2537 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302538
Jeff Johnson295189b2012-06-20 16:38:30 -07002539 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2540 __func__,pAdapter->device_mode);
2541
2542 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002543 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302544 )
Jeff Johnson295189b2012-06-20 16:38:30 -07002545 {
2546 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2547 * want to update this parameter */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302548 if (-1 != params->ap_isolate)
Jeff Johnson295189b2012-06-20 16:38:30 -07002549 {
2550 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302551 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002552 }
2553
2554 EXIT();
2555 return 0;
2556}
2557
2558/*
2559 * FUNCTION: wlan_hdd_cfg80211_change_iface
2560 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2561 */
2562int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2563 struct net_device *ndev,
2564 enum nl80211_iftype type,
2565 u32 *flags,
2566 struct vif_params *params
2567 )
2568{
2569 struct wireless_dev *wdev;
2570 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2571 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002572 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002573 tCsrRoamProfile *pRoamProfile = NULL;
2574 eCsrRoamBssType LastBSSType;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302575 hdd_config_t *pConfig = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002576 eMib_dot11DesiredBssType connectedBssType;
2577 VOS_STATUS status;
2578
2579 ENTER();
2580
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302581 status = wlan_hdd_validate_context(pHddCtx);
2582
2583 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07002584 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302585 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2586 "%s: HDD context is not valid", __func__);
2587 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002588 }
2589
2590 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2591 __func__, pAdapter->device_mode);
2592
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302593 pConfig = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07002594 wdev = ndev->ieee80211_ptr;
2595
2596#ifdef WLAN_BTAMP_FEATURE
2597 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2598 (NL80211_IFTYPE_ADHOC == type)||
2599 (NL80211_IFTYPE_AP == type)||
2600 (NL80211_IFTYPE_P2P_GO == type))
2601 {
2602 pHddCtx->isAmpAllowed = VOS_FALSE;
2603 // stop AMP traffic
2604 status = WLANBAP_StopAmp();
2605 if(VOS_STATUS_SUCCESS != status )
2606 {
2607 pHddCtx->isAmpAllowed = VOS_TRUE;
2608 hddLog(VOS_TRACE_LEVEL_FATAL,
2609 "%s: Failed to stop AMP", __func__);
2610 return -EINVAL;
2611 }
2612 }
2613#endif //WLAN_BTAMP_FEATURE
2614 /* Reset the current device mode bit mask*/
2615 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2616
2617 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07002618 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002619 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002620 )
2621 {
2622 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2623 pRoamProfile = &pWextState->roamProfile;
2624 LastBSSType = pRoamProfile->BSSType;
2625
2626 switch (type)
2627 {
2628 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002629 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002630 hddLog(VOS_TRACE_LEVEL_INFO,
2631 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2632 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002633#ifdef WLAN_FEATURE_11AC
2634 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2635 {
2636 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2637 }
2638#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302639 pRoamProfile->phyMode =
Jeff Johnsone7245742012-09-05 17:12:55 -07002640 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002641 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002642 //Check for sub-string p2p to confirm its a p2p interface
2643 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302644 {
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002645 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2646 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2647 }
2648 else
2649 {
2650 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002651 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002652 }
Madan Mohan Koyyalamudi81746922013-07-17 14:38:51 +05302653#ifdef FEATURE_WLAN_TDLS
2654 /* The open adapter for the p2p shall skip initializations in
2655 * tdls_init if the device mode is WLAN_HDD_P2P_DEVICE, for
2656 * TDLS is supported only on WLAN_HDD_P2P_CLIENT. Hence invoke
2657 * tdls_init when the change_iface sets the device mode to
2658 * WLAN_HDD_P2P_CLIENT.
2659 */
2660
2661 if ( pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2662 {
2663 if (0 != wlan_hdd_tdls_init (pAdapter))
2664 {
2665 return -EINVAL;
2666 }
2667 }
2668#endif
2669
Jeff Johnson295189b2012-06-20 16:38:30 -07002670 break;
2671 case NL80211_IFTYPE_ADHOC:
2672 hddLog(VOS_TRACE_LEVEL_INFO,
2673 "%s: setting interface Type to ADHOC", __func__);
2674 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2675 pRoamProfile->phyMode =
2676 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Shailender Karmuchia734f332013-04-19 14:02:48 -07002677 pAdapter->device_mode = WLAN_HDD_IBSS;
Jeff Johnson295189b2012-06-20 16:38:30 -07002678 wdev->iftype = type;
2679 break;
2680
2681 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002682 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002683 {
2684 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2685 "%s: setting interface Type to %s", __func__,
2686 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2687
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002688 //Cancel any remain on channel for GO mode
2689 if (NL80211_IFTYPE_P2P_GO == type)
2690 {
2691 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2692 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002693 if (NL80211_IFTYPE_AP == type)
2694 {
2695 /* As Loading WLAN Driver one interface being created for p2p device
2696 * address. This will take one HW STA and the max number of clients
2697 * that can connect to softAP will be reduced by one. so while changing
2698 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2699 * interface as it is not required in SoftAP mode.
2700 */
2701
2702 // Get P2P Adapter
2703 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2704
2705 if (pP2pAdapter)
2706 {
2707 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2708 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2709 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2710 }
2711 }
2712
Jeff Johnson295189b2012-06-20 16:38:30 -07002713 //De-init the adapter.
2714 hdd_stop_adapter( pHddCtx, pAdapter );
2715 hdd_deinit_adapter( pHddCtx, pAdapter );
2716 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
Jeff Johnson295189b2012-06-20 16:38:30 -07002717 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2718 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002719
2720 //Disable BMPS and IMPS if enabled
2721 //before starting Go
2722 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2723 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302724 if(VOS_STATUS_E_FAILURE ==
Jeff Johnson32d95a32012-09-10 13:15:23 -07002725 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2726 {
2727 //Fail to Exit BMPS
2728 VOS_ASSERT(0);
2729 }
2730 }
2731
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002732 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2733 (pConfig->apRandomBssidEnabled))
2734 {
2735 /* To meet Android requirements create a randomized
2736 MAC address of the form 02:1A:11:Fx:xx:xx */
2737 get_random_bytes(&ndev->dev_addr[3], 3);
2738 ndev->dev_addr[0] = 0x02;
2739 ndev->dev_addr[1] = 0x1A;
2740 ndev->dev_addr[2] = 0x11;
2741 ndev->dev_addr[3] |= 0xF0;
2742 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2743 VOS_MAC_ADDR_SIZE);
2744 pr_info("wlan: Generated HotSpot BSSID "
2745 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2746 ndev->dev_addr[0],
2747 ndev->dev_addr[1],
2748 ndev->dev_addr[2],
2749 ndev->dev_addr[3],
2750 ndev->dev_addr[4],
2751 ndev->dev_addr[5]);
2752 }
2753
Jeff Johnson295189b2012-06-20 16:38:30 -07002754 hdd_set_ap_ops( pAdapter->dev );
2755
2756 status = hdd_init_ap_mode(pAdapter);
2757 if(status != VOS_STATUS_SUCCESS)
2758 {
2759 hddLog(VOS_TRACE_LEVEL_FATAL,
2760 "%s: Error initializing the ap mode", __func__);
2761 return -EINVAL;
2762 }
2763 hdd_set_conparam(1);
2764
Jeff Johnson295189b2012-06-20 16:38:30 -07002765 /*interface type changed update in wiphy structure*/
2766 if(wdev)
2767 {
2768 wdev->iftype = type;
2769 pHddCtx->change_iface = type;
2770 }
2771 else
2772 {
2773 hddLog(VOS_TRACE_LEVEL_ERROR,
2774 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2775 return -EINVAL;
2776 }
2777 goto done;
2778 }
2779
2780 default:
2781 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2782 __func__);
2783 return -EOPNOTSUPP;
2784 }
2785 }
2786 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002787 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002788 )
2789 {
2790 switch(type)
2791 {
2792 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002793 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002794 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002795 hdd_stop_adapter( pHddCtx, pAdapter );
2796 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002797 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002798 //Check for sub-string p2p to confirm its a p2p interface
2799 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002800 {
2801 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2802 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2803 }
2804 else
2805 {
2806 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002807 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002808 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002809 hdd_set_conparam(0);
2810 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002811 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2812 hdd_set_station_ops( pAdapter->dev );
2813 status = hdd_init_station_mode( pAdapter );
2814 if( VOS_STATUS_SUCCESS != status )
2815 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002816 /* In case of JB, for P2P-GO, only change interface will be called,
2817 * This is the right place to enable back bmps_imps()
2818 */
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05302819 if (pHddCtx->hdd_wlan_suspended)
2820 {
2821 hdd_set_pwrparams(pHddCtx);
2822 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002823 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002824 goto done;
2825 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002826 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002827 wdev->iftype = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002828 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2829 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07002830 goto done;
2831 default:
2832 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2833 __func__);
2834 return -EOPNOTSUPP;
2835
2836 }
2837
2838 }
2839 else
2840 {
2841 return -EOPNOTSUPP;
2842 }
2843
2844
2845 if(pRoamProfile)
2846 {
2847 if ( LastBSSType != pRoamProfile->BSSType )
2848 {
2849 /*interface type changed update in wiphy structure*/
2850 wdev->iftype = type;
2851
2852 /*the BSS mode changed, We need to issue disconnect
2853 if connected or in IBSS disconnect state*/
2854 if ( hdd_connGetConnectedBssType(
2855 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2856 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2857 {
2858 /*need to issue a disconnect to CSR.*/
2859 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2860 if( eHAL_STATUS_SUCCESS ==
2861 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2862 pAdapter->sessionId,
2863 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2864 {
2865 wait_for_completion_interruptible_timeout(
2866 &pAdapter->disconnect_comp_var,
2867 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2868 }
2869 }
2870 }
2871 }
2872
2873done:
2874 /*set bitmask based on updated value*/
2875 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
Leo Chang6fe1f922013-06-07 19:21:24 -07002876
2877 /* Only STA mode support TM now
2878 * all other mode, TM feature should be disabled */
2879 if ( (pHddCtx->cfg_ini->thermalMitigationEnable) &&
2880 (~VOS_STA & pHddCtx->concurrency_mode) )
2881 {
2882 hddDevTmLevelChangedHandler(pHddCtx->parent_dev, 0);
2883 }
2884
Jeff Johnson295189b2012-06-20 16:38:30 -07002885#ifdef WLAN_BTAMP_FEATURE
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302886 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07002887 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2888 {
2889 //we are ok to do AMP
2890 pHddCtx->isAmpAllowed = VOS_TRUE;
2891 }
2892#endif //WLAN_BTAMP_FEATURE
2893 EXIT();
2894 return 0;
2895}
2896
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002897#ifdef FEATURE_WLAN_TDLS
2898static int wlan_hdd_tdls_add_station(struct wiphy *wiphy,
2899 struct net_device *dev, u8 *mac, bool update, tCsrStaParams *StaParams)
2900{
2901 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2902 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2903 VOS_STATUS status;
Hoonki Lee5305c3a2013-04-29 23:28:59 -07002904 hddTdlsPeer_t *pTdlsPeer;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002905
2906 ENTER();
2907
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05302908 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002909 {
2910 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2911 "Invalid arguments");
2912 return -EINVAL;
2913 }
Hoonki Lee27511902013-03-14 18:19:06 -07002914
2915 if ((eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) ||
2916 (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode))
2917 {
2918 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2919 "%s: TDLS mode is disabled OR not enabled in FW."
2920 MAC_ADDRESS_STR " Request declined.",
2921 __func__, MAC_ADDR_ARRAY(mac));
2922 return -ENOTSUPP;
2923 }
2924
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002925 if (pHddCtx->isLogpInProgress)
2926 {
2927 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2928 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07002929 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002930 return -EBUSY;
2931 }
2932
Hoonki Lee5305c3a2013-04-29 23:28:59 -07002933 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac);
2934
2935 if ( NULL == pTdlsPeer ) {
2936 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2937 "%s: " MAC_ADDRESS_STR " (update %d) not exist. return invalid",
2938 __func__, MAC_ADDR_ARRAY(mac), update);
2939 return -EINVAL;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002940 }
Hoonki Lee5305c3a2013-04-29 23:28:59 -07002941
2942 /* in add station, we accept existing valid staId if there is */
2943 if ((0 == update) &&
2944 ((pTdlsPeer->link_status >= eTDLS_LINK_CONNECTING) ||
2945 (TDLS_STA_INDEX_VALID(pTdlsPeer->staId))))
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002946 {
Hoonki Lee5305c3a2013-04-29 23:28:59 -07002947 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002948 "%s: " MAC_ADDRESS_STR
Hoonki Lee5305c3a2013-04-29 23:28:59 -07002949 " link_status %d. staId %d. add station ignored.",
2950 __func__, MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status, pTdlsPeer->staId);
2951 return 0;
2952 }
2953 /* in change station, we accept only when staId is valid */
2954 if ((1 == update) &&
2955 ((pTdlsPeer->link_status > eTDLS_LINK_CONNECTING) ||
2956 (!TDLS_STA_INDEX_VALID(pTdlsPeer->staId))))
2957 {
2958 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2959 "%s: " MAC_ADDRESS_STR
2960 " link status %d. staId %d. change station %s.",
2961 __func__, MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status, pTdlsPeer->staId,
2962 (TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) ? "ignored" : "declined");
2963 return (TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) ? 0 : -EPERM;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002964 }
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002965
2966 /* when others are on-going, we want to change link_status to idle */
Hoonki Leefb8df672013-04-10 18:20:34 -07002967 if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, mac, TRUE, TRUE))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002968 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002969 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2970 "%s: " MAC_ADDRESS_STR
2971 " TDLS setup is ongoing. Request declined.",
2972 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002973 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002974 }
2975
2976 /* first to check if we reached to maximum supported TDLS peer.
2977 TODO: for now, return -EPERM looks working fine,
2978 but need to check if any other errno fit into this category.*/
2979 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
2980 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002981 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2982 "%s: " MAC_ADDRESS_STR
2983 " TDLS Max peer already connected. Request declined.",
2984 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002985 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002986 }
2987 else
2988 {
2989 hddTdlsPeer_t *pTdlsPeer;
2990 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002991 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002992 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002993 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2994 "%s: " MAC_ADDRESS_STR " already connected. Request declined.",
2995 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002996 return -EPERM;
2997 }
2998 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002999 if (0 == update)
3000 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_CONNECTING);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003001
Jeff Johnsond75fe012013-04-06 10:53:06 -07003002 /* debug code */
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05303003 if (NULL != StaParams)
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003004 {
3005 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3006 "%s: TDLS Peer Parameters.", __func__);
Hoonki Lee66b75f32013-04-16 18:30:07 -07003007 if(StaParams->htcap_present)
3008 {
3009 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3010 "ht_capa->cap_info: %0x", StaParams->HTCap.capInfo);
3011 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3012 "ht_capa->extended_capabilities: %0x",
3013 StaParams->HTCap.extendedHtCapInfo);
3014 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003015 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3016 "params->capability: %0x",StaParams->capability);
3017 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3018 "params->ext_capab_len: %0x",StaParams->extn_capability);
Hoonki Lee66b75f32013-04-16 18:30:07 -07003019 if(StaParams->vhtcap_present)
3020 {
3021 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3022 "rxMcsMap %x rxHighest %x txMcsMap %x txHighest %x",
3023 StaParams->VHTCap.suppMcs.rxMcsMap, StaParams->VHTCap.suppMcs.rxHighest,
3024 StaParams->VHTCap.suppMcs.txMcsMap, StaParams->VHTCap.suppMcs.txHighest);
3025 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003026 {
3027 int i = 0;
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003028 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "Supported rates:");
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003029 for (i = 0; i < sizeof(StaParams->supported_rates); i++)
3030 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3031 "[%d]: %x ", i, StaParams->supported_rates[i]);
3032 }
Jeff Johnsond75fe012013-04-06 10:53:06 -07003033 } /* end debug code */
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05303034 else if ((1 == update) && (NULL == StaParams))
3035 {
3036 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3037 "%s : update is true, but staParams is NULL. Error!", __func__);
3038 return -EPERM;
3039 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003040
3041 INIT_COMPLETION(pAdapter->tdls_add_station_comp);
3042
3043 if (!update)
3044 {
3045 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
3046 pAdapter->sessionId, mac);
3047 }
3048 else
3049 {
3050 status = sme_ChangeTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
3051 pAdapter->sessionId, mac, StaParams);
3052 }
3053
3054 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_add_station_comp,
3055 msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
3056
3057 if (!status)
3058 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003059 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003060 "%s: timeout waiting for tdls add station indication",
3061 __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07003062 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003063 }
3064 if ( eHAL_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus)
3065 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003066 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003067 "%s: Add Station is unsucessful", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07003068 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003069 }
3070
3071 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07003072
3073error:
3074 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
3075 return -EPERM;
3076
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003077}
3078#endif
3079
Jeff Johnson295189b2012-06-20 16:38:30 -07003080static int wlan_hdd_change_station(struct wiphy *wiphy,
3081 struct net_device *dev,
3082 u8 *mac,
3083 struct station_parameters *params)
3084{
3085 VOS_STATUS status = VOS_STATUS_SUCCESS;
3086 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Gopichand Nakkala29149562013-05-10 21:43:41 +05303087 hdd_context_t *pHddCtx;
3088 hdd_station_ctx_t *pHddStaCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003089 v_MACADDR_t STAMacAddress;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003090#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003091 tCsrStaParams StaParams = {0};
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003092 tANI_U8 isBufSta = 0;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003093#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003094 ENTER();
3095
Gopichand Nakkala29149562013-05-10 21:43:41 +05303096 if ((NULL == pAdapter))
3097 {
3098 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3099 "invalid adapter ");
3100 return -EINVAL;
3101 }
3102
3103 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3104 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3105
3106 if ((NULL == pHddCtx) || (NULL == pHddStaCtx))
3107 {
3108 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3109 "invalid HDD state or HDD station context");
3110 return -EINVAL;
3111 }
3112
3113 if (pHddCtx->isLogpInProgress)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003114 {
3115 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3116 "%s:LOGP in Progress. Ignore!!!", __func__);
3117 return -EAGAIN;
3118 }
3119
Jeff Johnson295189b2012-06-20 16:38:30 -07003120 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
3121
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003122 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3123 || (pAdapter->device_mode == WLAN_HDD_P2P_GO))
Jeff Johnson295189b2012-06-20 16:38:30 -07003124 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003125 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
Jeff Johnson295189b2012-06-20 16:38:30 -07003126 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303127 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
Jeff Johnson295189b2012-06-20 16:38:30 -07003128 WLANTL_STA_AUTHENTICATED);
3129
Gopichand Nakkala29149562013-05-10 21:43:41 +05303130 if (status != VOS_STATUS_SUCCESS)
3131 {
3132 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3133 "%s: Not able to change TL state to AUTHENTICATED", __func__);
3134 return -EINVAL;
3135 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003136 }
3137 }
Hoonki Leea6d49be2013-04-05 09:43:25 -07003138 else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3139 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) {
Gopichand Nakkala29149562013-05-10 21:43:41 +05303140#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003141 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
3142 StaParams.capability = params->capability;
3143 StaParams.uapsd_queues = params->uapsd_queues;
3144 StaParams.max_sp = params->max_sp;
3145
3146 if (0 != params->ext_capab_len)
3147 vos_mem_copy(StaParams.extn_capability, params->ext_capab,
3148 sizeof(StaParams.extn_capability));
3149
3150 if (NULL != params->ht_capa)
Hoonki Lee66b75f32013-04-16 18:30:07 -07003151 {
3152 StaParams.htcap_present = 1;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003153 vos_mem_copy(&StaParams.HTCap, params->ht_capa, sizeof(tSirHTCap));
Hoonki Lee66b75f32013-04-16 18:30:07 -07003154 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003155
3156 StaParams.supported_rates_len = params->supported_rates_len;
3157
3158 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
3159 * The supported_rates array , for all the structures propogating till Add Sta
3160 * to the firmware has to be modified , if the supplicant (ieee80211) is
3161 * modified to send more rates.
3162 */
3163
3164 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
3165 */
3166 if (StaParams.supported_rates_len > SIR_MAC_MAX_SUPP_RATES)
3167 StaParams.supported_rates_len = SIR_MAC_MAX_SUPP_RATES;
3168
3169 if (0 != StaParams.supported_rates_len) {
3170 int i = 0;
3171 vos_mem_copy(StaParams.supported_rates, params->supported_rates,
3172 StaParams.supported_rates_len);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003173 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003174 "Supported Rates with Length %d", StaParams.supported_rates_len);
3175 for (i=0; i < StaParams.supported_rates_len; i++)
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003176 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003177 "[%d]: %0x", i, StaParams.supported_rates[i]);
3178 }
3179
3180 if (NULL != params->vht_capa)
Hoonki Lee66b75f32013-04-16 18:30:07 -07003181 {
3182 StaParams.vhtcap_present = 1;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003183 vos_mem_copy(&StaParams.VHTCap, params->vht_capa, sizeof(tSirVHTCap));
Hoonki Lee66b75f32013-04-16 18:30:07 -07003184 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003185
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003186 if (0 != params->ext_capab_len ) {
3187 /*Define A Macro : TODO Sunil*/
3188 if ((1<<4) & StaParams.extn_capability[3]) {
3189 isBufSta = 1;
3190 }
3191 }
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303192 status = wlan_hdd_tdls_set_peer_caps( pAdapter, mac, params->uapsd_queues,
3193 params->max_sp, isBufSta);
3194 if (VOS_STATUS_SUCCESS != status) {
3195 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3196 "%s: wlan_hdd_tdls_set_peer_caps failed!", __func__);
3197 return -EINVAL;
3198 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003199 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 1, &StaParams);
3200
3201 if (VOS_STATUS_SUCCESS != status) {
3202 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3203 "%s: sme_ChangeTdlsPeerSta failed!", __func__);
3204 return -EINVAL;
3205 }
3206 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003207#endif
Gopichand Nakkala6239acd2013-06-14 14:48:00 +05303208 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003209 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003210 return status;
3211}
3212
3213/*
Jeff Johnson295189b2012-06-20 16:38:30 -07003214 * FUNCTION: wlan_hdd_cfg80211_add_key
3215 * This function is used to initialize the key information
3216 */
3217#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003218static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003219 struct net_device *ndev,
3220 u8 key_index, bool pairwise,
3221 const u8 *mac_addr,
3222 struct key_params *params
3223 )
3224#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003225static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003226 struct net_device *ndev,
3227 u8 key_index, const u8 *mac_addr,
3228 struct key_params *params
3229 )
3230#endif
3231{
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003232 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003233 tCsrRoamSetKey setKey;
3234 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303235 int status;
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003236 v_U32_t roamId= 0xFF;
3237 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003238 hdd_hostapd_state_t *pHostapdState;
3239 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003240 eHalStatus halStatus;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303241 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003242
3243 ENTER();
3244
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303245 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3246 status = wlan_hdd_validate_context(pHddCtx);
3247
3248 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003249 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303250 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3251 "%s: HDD context is not valid", __func__);
3252 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003253 }
3254
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003255 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
3256 __func__, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003257
3258 if (CSR_MAX_NUM_KEY <= key_index)
3259 {
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003260 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003261 key_index);
3262
3263 return -EINVAL;
3264 }
3265
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003266 if (CSR_MAX_KEY_LEN < params->key_len)
3267 {
3268 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key length %d", __func__,
3269 params->key_len);
3270
3271 return -EINVAL;
3272 }
3273
3274 hddLog(VOS_TRACE_LEVEL_INFO,
3275 "%s: called with key index = %d & key length %d",
3276 __func__, key_index, params->key_len);
Jeff Johnson295189b2012-06-20 16:38:30 -07003277
3278 /*extract key idx, key len and key*/
3279 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3280 setKey.keyId = key_index;
3281 setKey.keyLength = params->key_len;
3282 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
3283
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003284 switch (params->cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07003285 {
3286 case WLAN_CIPHER_SUITE_WEP40:
3287 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
3288 break;
3289
3290 case WLAN_CIPHER_SUITE_WEP104:
3291 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
3292 break;
3293
3294 case WLAN_CIPHER_SUITE_TKIP:
3295 {
3296 u8 *pKey = &setKey.Key[0];
3297 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
3298
3299 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
3300
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003301 /*Supplicant sends the 32bytes key in this order
Jeff Johnson295189b2012-06-20 16:38:30 -07003302
3303 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003304 | Tk1 |TX-MIC | RX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003305 |--------------|----------|----------|
3306 <---16bytes---><--8bytes--><--8bytes-->
3307
3308 */
3309 /*Sme expects the 32 bytes key to be in the below order
3310
3311 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003312 | Tk1 |RX-MIC | TX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003313 |--------------|----------|----------|
3314 <---16bytes---><--8bytes--><--8bytes-->
3315 */
3316 /* Copy the Temporal Key 1 (TK1) */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003317 vos_mem_copy(pKey, params->key, 16);
Jeff Johnson295189b2012-06-20 16:38:30 -07003318
3319 /*Copy the rx mic first*/
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003320 vos_mem_copy(&pKey[16], &params->key[24], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003321
3322 /*Copy the tx mic */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003323 vos_mem_copy(&pKey[24], &params->key[16], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003324
3325
3326 break;
3327 }
3328
3329 case WLAN_CIPHER_SUITE_CCMP:
3330 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
3331 break;
3332
3333#ifdef FEATURE_WLAN_WAPI
3334 case WLAN_CIPHER_SUITE_SMS4:
3335 {
3336 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3337 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
3338 params->key, params->key_len);
3339 return 0;
3340 }
3341#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003342
Jeff Johnson295189b2012-06-20 16:38:30 -07003343#ifdef FEATURE_WLAN_CCX
3344 case WLAN_CIPHER_SUITE_KRK:
3345 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
3346 break;
3347#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003348
3349#ifdef WLAN_FEATURE_11W
3350 case WLAN_CIPHER_SUITE_AES_CMAC:
3351 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
Chet Lanctot3b5158a2013-03-31 16:45:21 -07003352 break;
Chet Lanctot186b5732013-03-18 10:26:30 -07003353#endif
3354
Jeff Johnson295189b2012-06-20 16:38:30 -07003355 default:
3356 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
3357 __func__, params->cipher);
3358 return -EOPNOTSUPP;
3359 }
3360
3361 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
3362 __func__, setKey.encType);
3363
Shailender Karmuchi642e9812013-05-30 14:34:49 -07003364 if (
Jeff Johnson295189b2012-06-20 16:38:30 -07003365#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3366 (!pairwise)
3367#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003368 (!mac_addr || is_broadcast_ether_addr(mac_addr))
Jeff Johnson295189b2012-06-20 16:38:30 -07003369#endif
Shailender Karmuchi642e9812013-05-30 14:34:49 -07003370 )
3371 {
3372 /* set group key*/
3373 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3374 "%s- %d: setting Broadcast key",
3375 __func__, __LINE__);
3376 setKey.keyDirection = eSIR_RX_ONLY;
3377 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3378 }
3379 else
3380 {
3381 /* set pairwise key*/
3382 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3383 "%s- %d: setting pairwise key",
3384 __func__, __LINE__);
3385 setKey.keyDirection = eSIR_TX_RX;
3386 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3387 }
3388 if ((WLAN_HDD_IBSS == pAdapter->device_mode) && !pairwise)
3389 {
3390 setKey.keyDirection = eSIR_TX_RX;
3391 /*Set the group key*/
3392 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3393 pAdapter->sessionId, &setKey, &roamId );
Jeff Johnson295189b2012-06-20 16:38:30 -07003394
Shailender Karmuchi642e9812013-05-30 14:34:49 -07003395 if ( 0 != status )
3396 {
3397 hddLog(VOS_TRACE_LEVEL_ERROR,
3398 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3399 return -EINVAL;
3400 }
3401 /*Save the keys here and call sme_RoamSetKey for setting
3402 the PTK after peer joins the IBSS network*/
3403 vos_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
3404 &setKey, sizeof(tCsrRoamSetKey));
3405 return status;
3406 }
Gopichand Nakkala29149562013-05-10 21:43:41 +05303407 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) ||
3408 (pAdapter->device_mode == WLAN_HDD_P2P_GO))
3409 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003410 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003411 if( pHostapdState->bssState == BSS_START )
3412 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003413 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3414
3415 if ( status != eHAL_STATUS_SUCCESS )
3416 {
3417 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3418 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3419 __LINE__, status );
3420 }
3421 }
3422
3423 /* Saving WEP keys */
3424 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
3425 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
3426 {
3427 //Save the wep key in ap context. Issue setkey after the BSS is started.
3428 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3429 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
3430 }
3431 else
3432 {
3433 //Save the key in ap context. Issue setkey after the BSS is started.
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003434 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003435 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
3436 }
3437 }
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003438 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
3439 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) )
Jeff Johnson295189b2012-06-20 16:38:30 -07003440 {
3441 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3442 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3443
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303444#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3445 if (!pairwise)
3446#else
3447 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
3448#endif
3449 {
3450 /* set group key*/
3451 if (pHddStaCtx->roam_info.deferKeyComplete)
3452 {
3453 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3454 "%s- %d: Perform Set key Complete",
3455 __func__, __LINE__);
3456 hdd_PerformRoamSetKeyComplete(pAdapter);
3457 }
3458 }
3459
Jeff Johnson295189b2012-06-20 16:38:30 -07003460 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
3461
Venkata Prathyusha Kuntupalliee2ce712013-01-17 14:09:24 -08003462 pWextState->roamProfile.Keys.defaultIndex = key_index;
3463
3464
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003465 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07003466 params->key, params->key_len);
3467
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303468
Jeff Johnson295189b2012-06-20 16:38:30 -07003469 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3470
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303471 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07003472 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303473 __func__, setKey.peerMac[0], setKey.peerMac[1],
3474 setKey.peerMac[2], setKey.peerMac[3],
3475 setKey.peerMac[4], setKey.peerMac[5],
Jeff Johnson295189b2012-06-20 16:38:30 -07003476 setKey.keyDirection);
3477
3478 vos_status = wlan_hdd_check_ula_done(pAdapter);
3479
3480 if ( vos_status != VOS_STATUS_SUCCESS )
3481 {
3482 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3483 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
3484 __LINE__, vos_status );
3485
3486 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3487
3488 return -EINVAL;
3489
3490 }
3491
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003492#ifdef WLAN_FEATURE_VOWIFI_11R
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303493 /* The supplicant may attempt to set the PTK once pre-authentication
3494 is done. Save the key in the UMAC and include it in the ADD BSS
3495 request */
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003496 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303497 if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS )
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003498 {
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303499 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3500 "%s: Update PreAuth Key success", __func__);
3501 return 0;
3502 }
3503 else if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_FAILED )
3504 {
3505 hddLog(VOS_TRACE_LEVEL_ERROR,
3506 "%s: Update PreAuth Key failed", __func__);
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303507 return -EINVAL;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003508 }
3509#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07003510
3511 /* issue set key request to SME*/
3512 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3513 pAdapter->sessionId, &setKey, &roamId );
3514
3515 if ( 0 != status )
3516 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303517 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003518 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3519 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3520 return -EINVAL;
3521 }
3522
3523
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303524 /* in case of IBSS as there was no information available about WEP keys during
3525 * IBSS join, group key intialized with NULL key, so re-initialize group key
Jeff Johnson295189b2012-06-20 16:38:30 -07003526 * with correct value*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303527 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
3528 !( ( IW_AUTH_KEY_MGMT_802_1X
3529 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
Jeff Johnson295189b2012-06-20 16:38:30 -07003530 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3531 )
3532 &&
3533 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3534 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3535 )
3536 )
3537 {
3538 setKey.keyDirection = eSIR_RX_ONLY;
3539 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3540
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303541 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07003542 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303543 __func__, setKey.peerMac[0], setKey.peerMac[1],
3544 setKey.peerMac[2], setKey.peerMac[3],
3545 setKey.peerMac[4], setKey.peerMac[5],
Jeff Johnson295189b2012-06-20 16:38:30 -07003546 setKey.keyDirection);
3547
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303548 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07003549 pAdapter->sessionId, &setKey, &roamId );
3550
3551 if ( 0 != status )
3552 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303553 hddLog(VOS_TRACE_LEVEL_ERROR,
3554 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07003555 __func__, status);
3556 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3557 return -EINVAL;
3558 }
3559 }
3560 }
3561
3562 return 0;
3563}
3564
3565/*
3566 * FUNCTION: wlan_hdd_cfg80211_get_key
3567 * This function is used to get the key information
3568 */
3569#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303570static int wlan_hdd_cfg80211_get_key(
3571 struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003572 struct net_device *ndev,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303573 u8 key_index, bool pairwise,
Jeff Johnson295189b2012-06-20 16:38:30 -07003574 const u8 *mac_addr, void *cookie,
3575 void (*callback)(void *cookie, struct key_params*)
3576 )
3577#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303578static int wlan_hdd_cfg80211_get_key(
3579 struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003580 struct net_device *ndev,
3581 u8 key_index, const u8 *mac_addr, void *cookie,
3582 void (*callback)(void *cookie, struct key_params*)
3583 )
3584#endif
3585{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303586 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003587 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3588 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
3589 struct key_params params;
3590
3591 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303592
Jeff Johnson295189b2012-06-20 16:38:30 -07003593 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3594 __func__,pAdapter->device_mode);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303595
Jeff Johnson295189b2012-06-20 16:38:30 -07003596 memset(&params, 0, sizeof(params));
3597
3598 if (CSR_MAX_NUM_KEY <= key_index)
3599 {
3600 return -EINVAL;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303601 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003602
3603 switch(pRoamProfile->EncryptionType.encryptionType[0])
3604 {
3605 case eCSR_ENCRYPT_TYPE_NONE:
3606 params.cipher = IW_AUTH_CIPHER_NONE;
3607 break;
3608
3609 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3610 case eCSR_ENCRYPT_TYPE_WEP40:
3611 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3612 break;
3613
3614 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3615 case eCSR_ENCRYPT_TYPE_WEP104:
3616 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3617 break;
3618
3619 case eCSR_ENCRYPT_TYPE_TKIP:
3620 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3621 break;
3622
3623 case eCSR_ENCRYPT_TYPE_AES:
3624 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3625 break;
3626
3627 default:
3628 params.cipher = IW_AUTH_CIPHER_NONE;
3629 break;
3630 }
3631
3632 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3633 params.seq_len = 0;
3634 params.seq = NULL;
3635 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3636 callback(cookie, &params);
3637 return 0;
3638}
3639
3640/*
3641 * FUNCTION: wlan_hdd_cfg80211_del_key
3642 * This function is used to delete the key information
3643 */
3644#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303645static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003646 struct net_device *ndev,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303647 u8 key_index,
3648 bool pairwise,
Jeff Johnson295189b2012-06-20 16:38:30 -07003649 const u8 *mac_addr
3650 )
3651#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303652static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003653 struct net_device *ndev,
3654 u8 key_index,
3655 const u8 *mac_addr
3656 )
3657#endif
3658{
3659 int status = 0;
3660
3661 //This code needs to be revisited. There is sme_removeKey API, we should
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303662 //plan to use that. After the change to use correct index in setkey,
Jeff Johnson295189b2012-06-20 16:38:30 -07003663 //it is observed that this is invalidating peer
3664 //key index whenever re-key is done. This is affecting data link.
3665 //It should be ok to ignore del_key.
3666#if 0
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303667 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3668 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003669 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3670 tCsrRoamSetKey setKey;
3671 v_U32_t roamId= 0xFF;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303672
Jeff Johnson295189b2012-06-20 16:38:30 -07003673 ENTER();
3674
3675 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3676 __func__,pAdapter->device_mode);
3677
3678 if (CSR_MAX_NUM_KEY <= key_index)
3679 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303680 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003681 key_index);
3682
3683 return -EINVAL;
3684 }
3685
3686 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3687 setKey.keyId = key_index;
3688
3689 if (mac_addr)
3690 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3691 else
3692 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3693
3694 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3695
3696 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003697 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303698 )
3699 {
3700
3701 hdd_hostapd_state_t *pHostapdState =
Jeff Johnson295189b2012-06-20 16:38:30 -07003702 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3703 if( pHostapdState->bssState == BSS_START)
3704 {
3705 status = WLANSAP_SetKeySta( pVosContext, &setKey);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303706
Jeff Johnson295189b2012-06-20 16:38:30 -07003707 if ( status != eHAL_STATUS_SUCCESS )
3708 {
3709 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3710 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3711 __LINE__, status );
3712 }
3713 }
3714 }
3715 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303716 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003717 )
3718 {
3719 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3720
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303721 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3722
3723 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07003724 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303725 __func__, setKey.peerMac[0], setKey.peerMac[1],
3726 setKey.peerMac[2], setKey.peerMac[3],
Jeff Johnson295189b2012-06-20 16:38:30 -07003727 setKey.peerMac[4], setKey.peerMac[5]);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303728 if(pAdapter->sessionCtx.station.conn_info.connState ==
3729 eConnectionState_Associated)
Jeff Johnson295189b2012-06-20 16:38:30 -07003730 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303731 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07003732 pAdapter->sessionId, &setKey, &roamId );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303733
Jeff Johnson295189b2012-06-20 16:38:30 -07003734 if ( 0 != status )
3735 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303736 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003737 "%s: sme_RoamSetKey failure, returned %d",
3738 __func__, status);
3739 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3740 return -EINVAL;
3741 }
3742 }
3743 }
3744#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003745 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003746 return status;
3747}
3748
3749/*
3750 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3751 * This function is used to set the default tx key index
3752 */
3753#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3754static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3755 struct net_device *ndev,
3756 u8 key_index,
3757 bool unicast, bool multicast)
3758#else
3759static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3760 struct net_device *ndev,
3761 u8 key_index)
3762#endif
3763{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303764 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303765 int status;
Gopichand Nakkala29149562013-05-10 21:43:41 +05303766 hdd_wext_state_t *pWextState;
3767 hdd_station_ctx_t *pHddStaCtx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303768 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003769
3770 ENTER();
3771
Gopichand Nakkala29149562013-05-10 21:43:41 +05303772 if ((NULL == pAdapter))
3773 {
3774 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3775 "invalid adapter");
3776 return -EINVAL;
3777 }
3778
3779 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3780 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3781
3782 if ((NULL == pWextState) || (NULL == pHddStaCtx))
3783 {
3784 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3785 "invalid Wext state or HDD context");
3786 return -EINVAL;
3787 }
3788
Jeff Johnson295189b2012-06-20 16:38:30 -07003789 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3790 __func__,pAdapter->device_mode, key_index);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303791
Jeff Johnson295189b2012-06-20 16:38:30 -07003792 if (CSR_MAX_NUM_KEY <= key_index)
3793 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303794 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003795 key_index);
3796
3797 return -EINVAL;
3798 }
3799
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303800 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3801 status = wlan_hdd_validate_context(pHddCtx);
3802
3803 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003804 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303805 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3806 "%s: HDD context is not valid", __func__);
3807 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003808 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303809
Jeff Johnson295189b2012-06-20 16:38:30 -07003810 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003811 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303812 )
Jeff Johnson295189b2012-06-20 16:38:30 -07003813 {
Gopichand Nakkala29149562013-05-10 21:43:41 +05303814 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
Jeff Johnson295189b2012-06-20 16:38:30 -07003815 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303816 (eCSR_ENCRYPT_TYPE_AES !=
Jeff Johnson295189b2012-06-20 16:38:30 -07003817 pWextState->roamProfile.EncryptionType.encryptionType[0])
3818 )
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303819 {
3820 /* if default key index is not same as previous one,
Jeff Johnson295189b2012-06-20 16:38:30 -07003821 * then update the default key index */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303822
Jeff Johnson295189b2012-06-20 16:38:30 -07003823 tCsrRoamSetKey setKey;
3824 v_U32_t roamId= 0xFF;
3825 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303826
3827 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07003828 __func__, key_index);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303829
Jeff Johnson295189b2012-06-20 16:38:30 -07003830 Keys->defaultIndex = (u8)key_index;
3831 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3832 setKey.keyId = key_index;
3833 setKey.keyLength = Keys->KeyLength[key_index];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303834
3835 vos_mem_copy(&setKey.Key[0],
3836 &Keys->KeyMaterial[key_index][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07003837 Keys->KeyLength[key_index]);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303838
Gopichand Nakkala29149562013-05-10 21:43:41 +05303839 setKey.keyDirection = eSIR_TX_RX;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303840
3841 vos_mem_copy(setKey.peerMac,
Jeff Johnson295189b2012-06-20 16:38:30 -07003842 &pHddStaCtx->conn_info.bssId[0],
3843 WNI_CFG_BSSID_LEN);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303844
Gopichand Nakkala29149562013-05-10 21:43:41 +05303845 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
3846 pWextState->roamProfile.EncryptionType.encryptionType[0] ==
3847 eCSR_ENCRYPT_TYPE_WEP104)
3848 {
3849 /*In the case of dynamic wep supplicant hardcodes DWEP type to eCSR_ENCRYPT_TYPE_WEP104
3850 even though ap is configured for WEP-40 encryption. In this canse the key length
3851 is 5 but the encryption type is 104 hence checking the key langht(5) and encryption
3852 type(104) and switching encryption type to 40*/
3853 pWextState->roamProfile.EncryptionType.encryptionType[0] =
3854 eCSR_ENCRYPT_TYPE_WEP40;
3855 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
3856 eCSR_ENCRYPT_TYPE_WEP40;
3857 }
3858
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303859 setKey.encType =
Jeff Johnson295189b2012-06-20 16:38:30 -07003860 pWextState->roamProfile.EncryptionType.encryptionType[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303861
Jeff Johnson295189b2012-06-20 16:38:30 -07003862 /* issue set key request */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303863 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07003864 pAdapter->sessionId, &setKey, &roamId );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303865
Jeff Johnson295189b2012-06-20 16:38:30 -07003866 if ( 0 != status )
3867 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303868 hddLog(VOS_TRACE_LEVEL_ERROR,
3869 "%s: sme_RoamSetKey failed, returned %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003870 status);
3871 return -EINVAL;
3872 }
3873 }
3874 }
3875
3876 /* In SoftAp mode setting key direction for default mode */
3877 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3878 {
3879 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3880 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3881 (eCSR_ENCRYPT_TYPE_AES !=
3882 pWextState->roamProfile.EncryptionType.encryptionType[0])
3883 )
3884 {
3885 /* Saving key direction for default key index to TX default */
3886 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3887 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3888 }
3889 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303890
Jeff Johnson295189b2012-06-20 16:38:30 -07003891 return status;
3892}
3893
Jeff Johnson295189b2012-06-20 16:38:30 -07003894/*
3895 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3896 * This function is used to inform the BSS details to nl80211 interface.
3897 */
3898static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3899 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3900{
3901 struct net_device *dev = pAdapter->dev;
3902 struct wireless_dev *wdev = dev->ieee80211_ptr;
3903 struct wiphy *wiphy = wdev->wiphy;
3904 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3905 int chan_no;
3906 int ie_length;
3907 const char *ie;
3908 unsigned int freq;
3909 struct ieee80211_channel *chan;
3910 int rssi = 0;
3911 struct cfg80211_bss *bss = NULL;
3912
3913 ENTER();
3914
3915 if( NULL == pBssDesc )
3916 {
3917 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3918 return bss;
3919 }
3920
3921 chan_no = pBssDesc->channelId;
3922 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3923 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3924
3925 if( NULL == ie )
3926 {
3927 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3928 return bss;
3929 }
3930
3931#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3932 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3933 {
3934 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3935 }
3936 else
3937 {
3938 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3939 }
3940#else
3941 freq = ieee80211_channel_to_frequency(chan_no);
3942#endif
3943
3944 chan = __ieee80211_get_channel(wiphy, freq);
3945
3946 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3947 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3948 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3949 if (bss == NULL)
3950 {
3951 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3952
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303953 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3954 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
Jeff Johnson295189b2012-06-20 16:38:30 -07003955 pBssDesc->capabilityInfo,
3956 pBssDesc->beaconInterval, ie, ie_length,
3957 rssi, GFP_KERNEL ));
3958}
3959 else
3960 {
3961 return bss;
3962 }
3963}
3964
3965
3966
3967/*
3968 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3969 * This function is used to inform the BSS details to nl80211 interface.
3970 */
3971struct cfg80211_bss*
3972wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3973 tSirBssDescription *bss_desc
3974 )
3975{
3976 /*
3977 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3978 already exists in bss data base of cfg80211 for that particular BSS ID.
3979 Using cfg80211_inform_bss_frame to update the bss entry instead of
3980 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3981 now there is no possibility to get the mgmt(probe response) frame from PE,
3982 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3983 cfg80211_inform_bss_frame.
3984 */
3985 struct net_device *dev = pAdapter->dev;
3986 struct wireless_dev *wdev = dev->ieee80211_ptr;
3987 struct wiphy *wiphy = wdev->wiphy;
3988 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003989#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3990 qcom_ie_age *qie_age = NULL;
3991 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3992#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003993 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003994#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003995 const char *ie =
3996 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3997 unsigned int freq;
3998 struct ieee80211_channel *chan;
3999 struct ieee80211_mgmt *mgmt =
4000 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
4001 struct cfg80211_bss *bss_status = NULL;
4002 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
4003 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07004004#ifdef WLAN_OPEN_SOURCE
4005 struct timespec ts;
4006#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004007
4008 ENTER();
4009
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07004010 if (!mgmt)
4011 return NULL;
4012
Jeff Johnson295189b2012-06-20 16:38:30 -07004013 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07004014
4015#ifdef WLAN_OPEN_SOURCE
4016 /* Android does not want the timestamp from the frame.
4017 Instead it wants a monotonic increasing value */
4018 get_monotonic_boottime(&ts);
4019 mgmt->u.probe_resp.timestamp =
4020 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
4021#else
4022 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07004023 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
4024 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07004025
4026#endif
4027
Jeff Johnson295189b2012-06-20 16:38:30 -07004028 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
4029 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08004030
4031#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
4032 /* GPS Requirement: need age ie per entry. Using vendor specific. */
4033 /* Assuming this is the last IE, copy at the end */
4034 ie_length -=sizeof(qcom_ie_age);
4035 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
4036 qie_age->element_id = QCOM_VENDOR_IE_ID;
4037 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
4038 qie_age->oui_1 = QCOM_OUI1;
4039 qie_age->oui_2 = QCOM_OUI2;
4040 qie_age->oui_3 = QCOM_OUI3;
4041 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
4042 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
4043#endif
4044
Jeff Johnson295189b2012-06-20 16:38:30 -07004045 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
Gopichand Nakkalad908ec82013-05-16 19:32:19 +05304046 if (bss_desc->fProbeRsp)
4047 {
4048 mgmt->frame_control |=
4049 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
4050 }
4051 else
4052 {
4053 mgmt->frame_control |=
4054 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
4055 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004056
4057#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304058 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07004059 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
4060 {
4061 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
4062 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304063 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07004064 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
4065
4066 {
4067 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
4068 }
4069 else
4070 {
4071 kfree(mgmt);
4072 return NULL;
4073 }
4074#else
4075 freq = ieee80211_channel_to_frequency(chan_no);
4076#endif
4077 chan = __ieee80211_get_channel(wiphy, freq);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08004078 /*when the band is changed on the fly using the GUI, three things are done
4079 * 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)
4080 * as part of the scan abort, message willbe queued to PE and we proceed with flushing and changinh the band.
4081 * pe will stop the scanning further and report back the results what ever it had till now by calling the call back function.
4082 * if the time between update band and scandone call back is sufficent enough the band change reflects in SME, SME validates the channels
4083 * and discards the channels correponding to previous band and calls back with zero bss results.
4084 * 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
4085 * all the channels correponding to previous band.this is due to race condition.but those channels are invalid to the new band and so
4086 * this function __ieee80211_get_channel will return NULL.Each time we report scan result with this pointer null warning kernel trace is printed.
4087 * if the scan results contain large number of APs continuosly kernel warning trace is printed and it will lead to apps watch dog bark.
4088 * So drop the bss and continue to next bss.
4089 */
4090 if(chan == NULL)
4091 {
4092 hddLog(VOS_TRACE_LEVEL_INFO, "%s chan pointer is NULL", __func__);
Chilam Ngc4244af2013-04-01 15:37:32 -07004093 kfree(mgmt);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08004094 return NULL;
4095 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004096 /*To keep the rssi icon of the connected AP in the scan window
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304097 *and the rssi icon of the wireless networks in sync
Jeff Johnson295189b2012-06-20 16:38:30 -07004098 * */
4099 if (( eConnectionState_Associated ==
4100 pAdapter->sessionCtx.station.conn_info.connState ) &&
4101 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
4102 pAdapter->sessionCtx.station.conn_info.bssId,
4103 WNI_CFG_BSSID_LEN)))
4104 {
4105 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
4106 rssi = (pAdapter->rssi * 100);
4107 }
4108 else
4109 {
4110 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
4111 }
4112
4113 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
4114 frame_len, rssi, GFP_KERNEL);
4115 kfree(mgmt);
4116 return bss_status;
4117}
4118
4119/*
4120 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
4121 * This function is used to update the BSS data base of CFG8011
4122 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304123struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07004124 tCsrRoamInfo *pRoamInfo
4125 )
4126{
4127 tCsrRoamConnectedProfile roamProfile;
4128 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4129 struct cfg80211_bss *bss = NULL;
4130
4131 ENTER();
4132
4133 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
4134 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
4135
4136 if (NULL != roamProfile.pBssDesc)
4137 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304138 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07004139 &roamProfile);
4140
4141 if (NULL == bss)
4142 {
4143 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
4144 __func__);
4145 }
4146
4147 sme_RoamFreeConnectProfile(hHal, &roamProfile);
4148 }
4149 else
4150 {
4151 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
4152 __func__);
4153 }
4154 return bss;
4155}
4156
4157/*
4158 * FUNCTION: wlan_hdd_cfg80211_update_bss
4159 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304160static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
4161 hdd_adapter_t *pAdapter
Jeff Johnson295189b2012-06-20 16:38:30 -07004162 )
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304163{
Jeff Johnson295189b2012-06-20 16:38:30 -07004164 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4165 tCsrScanResultInfo *pScanResult;
4166 eHalStatus status = 0;
4167 tScanResultHandle pResult;
4168 struct cfg80211_bss *bss_status = NULL;
4169
4170 ENTER();
4171
4172 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4173 {
4174 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
4175 return -EAGAIN;
4176 }
4177
4178 /*
4179 * start getting scan results and populate cgf80211 BSS database
4180 */
4181 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
4182
4183 /* no scan results */
4184 if (NULL == pResult)
4185 {
4186 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
4187 return status;
4188 }
4189
4190 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
4191
4192 while (pScanResult)
4193 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304194 /*
4195 * cfg80211_inform_bss() is not updating ie field of bss entry, if
4196 * entry already exists in bss data base of cfg80211 for that
4197 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
4198 * bss entry instead of cfg80211_inform_bss, But this call expects
4199 * mgmt packet as input. As of now there is no possibility to get
4200 * the mgmt(probe response) frame from PE, converting bss_desc to
Jeff Johnson295189b2012-06-20 16:38:30 -07004201 * ieee80211_mgmt(probe response) and passing to c
4202 * fg80211_inform_bss_frame.
4203 * */
4204
4205 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
4206 &pScanResult->BssDescriptor);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304207
Jeff Johnson295189b2012-06-20 16:38:30 -07004208
4209 if (NULL == bss_status)
4210 {
4211 hddLog(VOS_TRACE_LEVEL_INFO,
4212 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
4213 }
4214 else
4215 {
Yue Maf49ba872013-08-19 12:04:25 -07004216 cfg80211_put_bss(
4217#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
4218 wiphy,
4219#endif
4220 bss_status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004221 }
4222
4223 pScanResult = sme_ScanResultGetNext(hHal, pResult);
4224 }
4225
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304226 sme_ScanResultPurge(hHal, pResult);
Jeff Johnson295189b2012-06-20 16:38:30 -07004227
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304228 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004229}
4230
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004231void
4232hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
4233{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304234 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004235 "%02X:%02X:%02X:%02X:%02X:%02X\n",
4236 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
4237 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004238} /****** end hddPrintMacAddr() ******/
4239
4240void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004241hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004242{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304243 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004244 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
4245 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
4246 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
4247 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004248} /****** end hddPrintPmkId() ******/
4249
4250//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
4251//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
4252
4253//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
4254//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
4255
4256#define dump_bssid(bssid) \
4257 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004258 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
4259 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
4260 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004261 }
4262
4263#define dump_pmkid(pMac, pmkid) \
4264 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004265 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
4266 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
4267 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004268 }
4269
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07004270#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004271/*
4272 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
4273 * This function is used to notify the supplicant of a new PMKSA candidate.
4274 */
4275int wlan_hdd_cfg80211_pmksa_candidate_notify(
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304276 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004277 int index, bool preauth )
4278{
Jeff Johnsone7245742012-09-05 17:12:55 -07004279#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004280 struct net_device *dev = pAdapter->dev;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004281 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004282
4283 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07004284 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004285
4286 if( NULL == pRoamInfo )
4287 {
4288 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
4289 return -EINVAL;
4290 }
4291
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004292 if (eANI_BOOLEAN_TRUE == hdd_is_okc_mode_enabled(pHddCtx))
4293 {
4294 dump_bssid(pRoamInfo->bssid);
4295 cfg80211_pmksa_candidate_notify(dev, index,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004296 pRoamInfo->bssid, preauth, GFP_KERNEL);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004297 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004298#endif /* FEATURE_WLAN_OKC */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304299 return 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004300}
4301#endif //FEATURE_WLAN_LFR
4302
Jeff Johnson295189b2012-06-20 16:38:30 -07004303/*
4304 * FUNCTION: hdd_cfg80211_scan_done_callback
4305 * scanning callback function, called after finishing scan
4306 *
4307 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304308static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
Jeff Johnson295189b2012-06-20 16:38:30 -07004309 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
4310{
4311 struct net_device *dev = (struct net_device *) pContext;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304312 //struct wireless_dev *wdev = dev->ieee80211_ptr;
Jeff Johnson295189b2012-06-20 16:38:30 -07004313 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004314 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4315 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004316 struct cfg80211_scan_request *req = NULL;
4317 int ret = 0;
4318
4319 ENTER();
4320
4321 hddLog(VOS_TRACE_LEVEL_INFO,
4322 "%s called with halHandle = %p, pContext = %p,"
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304323 "scanID = %d, returned status = %d\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07004324 __func__, halHandle, pContext, (int) scanId, (int) status);
4325
4326 //Block on scan req completion variable. Can't wait forever though.
4327 ret = wait_for_completion_interruptible_timeout(
4328 &pScanInfo->scan_req_completion_event,
4329 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
4330 if (!ret)
4331 {
4332 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004333 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004334 }
4335
4336 if(pScanInfo->mScanPending != VOS_TRUE)
4337 {
4338 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004339 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004340 }
4341
4342 /* Check the scanId */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304343 if (pScanInfo->scanId != scanId)
Jeff Johnson295189b2012-06-20 16:38:30 -07004344 {
4345 hddLog(VOS_TRACE_LEVEL_INFO,
4346 "%s called with mismatched scanId pScanInfo->scanId = %d "
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304347 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
Jeff Johnson295189b2012-06-20 16:38:30 -07004348 (int) scanId);
4349 }
4350
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304351 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07004352 pAdapter);
4353
4354 if (0 > ret)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304355 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004356
4357
4358 /* If any client wait scan result through WEXT
4359 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004360 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07004361 {
4362 /* The other scan request waiting for current scan finish
4363 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004364 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004365 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004366 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004367 }
4368 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004369 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004370 {
4371 struct net_device *dev = pAdapter->dev;
4372 union iwreq_data wrqu;
4373 int we_event;
4374 char *msg;
4375
4376 memset(&wrqu, '\0', sizeof(wrqu));
4377 we_event = SIOCGIWSCAN;
4378 msg = NULL;
4379 wireless_send_event(dev, we_event, &wrqu, msg);
4380 }
4381 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004382 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004383
4384 /* Get the Scan Req */
4385 req = pAdapter->request;
4386
4387 if (!req)
4388 {
4389 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004390 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07004391 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004392 }
4393
4394 /*
4395 * setting up 0, just in case.
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304396 */
Jeff Johnson295189b2012-06-20 16:38:30 -07004397 req->n_ssids = 0;
4398 req->n_channels = 0;
4399 req->ie = 0;
4400
Jeff Johnson295189b2012-06-20 16:38:30 -07004401 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004402 /* Scan is no longer pending */
4403 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004404
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07004405 /*
4406 * cfg80211_scan_done informing NL80211 about completion
4407 * of scanning
4408 */
4409 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004410 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004411
Jeff Johnsone7245742012-09-05 17:12:55 -07004412allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004413 /* release the wake lock at the end of the scan*/
4414 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004415
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004416 /* Acquire wakelock to handle the case where APP's tries to suspend
4417 * immediatly after the driver gets connect request(i.e after scan)
4418 * from supplicant, this result in app's is suspending and not able
4419 * to process the connect request to AP */
Amar Singhal6144c002013-05-03 16:11:42 -07004420 hdd_allow_suspend_timeout(1000);
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004421
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004422#ifdef FEATURE_WLAN_TDLS
4423 wlan_hdd_tdls_scan_done_callback(pAdapter);
4424#endif
4425
Jeff Johnson295189b2012-06-20 16:38:30 -07004426 EXIT();
4427 return 0;
4428}
4429
4430/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004431 * FUNCTION: hdd_isScanAllowed
4432 * Go through each adapter and check if scan allowed
4433 *
4434 */
4435v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
4436{
4437 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4438 hdd_station_ctx_t *pHddStaCtx = NULL;
4439 hdd_adapter_t *pAdapter = NULL;
4440 VOS_STATUS status = 0;
4441 v_U8_t staId = 0;
4442 v_U8_t *staMac = NULL;
4443
4444 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4445
4446 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4447 {
4448 pAdapter = pAdapterNode->pAdapter;
4449
4450 if( pAdapter )
4451 {
4452 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304453 "%s: Adapter with device mode %d exists",
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004454 __func__, pAdapter->device_mode);
4455 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4456 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4457 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
4458 {
4459 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4460 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
4461 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
4462 {
4463 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
4464 hddLog(VOS_TRACE_LEVEL_ERROR,
4465 "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the "
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304466 "middle of WPS/EAPOL exchange.", __func__,
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004467 staMac[0], staMac[1], staMac[2],
4468 staMac[3], staMac[4], staMac[5]);
4469 return VOS_FALSE;
4470 }
4471 }
4472 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
4473 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
4474 {
4475 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
4476 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304477 if ((pAdapter->aStaInfo[staId].isUsed) &&
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004478 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
4479 {
4480 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
4481
4482 hddLog(VOS_TRACE_LEVEL_ERROR,
4483 "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the "
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304484 "middle of WPS/EAPOL exchange.", __func__,
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004485 staMac[0], staMac[1], staMac[2],
4486 staMac[3], staMac[4], staMac[5]);
4487 return VOS_FALSE;
4488 }
4489 }
4490 }
4491 }
4492 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4493 pAdapterNode = pNext;
4494 }
4495 hddLog(VOS_TRACE_LEVEL_INFO,
4496 "%s: Scan allowed", __func__);
4497 return VOS_TRUE;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304498}
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004499
4500/*
Jeff Johnson295189b2012-06-20 16:38:30 -07004501 * FUNCTION: wlan_hdd_cfg80211_scan
4502 * this scan respond to scan trigger and update cfg80211 scan database
4503 * later, scan dump command can be used to recieve scan results
4504 */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08004505int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
4506#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4507 struct net_device *dev,
4508#endif
4509 struct cfg80211_scan_request *request)
4510{
4511#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4512 struct net_device *dev = request->wdev->netdev;
4513#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304514 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07004515 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4516 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304517 hdd_config_t *cfg_param = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004518 tCsrScanRequest scanRequest;
4519 tANI_U8 *channelList = NULL, i;
4520 v_U32_t scanId = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304521 int status;
4522 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004523 v_U8_t* pP2pIe = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004524
4525 ENTER();
4526
4527 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4528 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004529
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304530 status = wlan_hdd_validate_context(pHddCtx);
4531
4532 if (0 != status)
4533 {
4534 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4535 "%s: HDD context is not valid", __func__);
4536 return status;
4537 }
4538
4539 cfg_param = pHddCtx->cfg_ini;
4540 pScanInfo = &pHddCtx->scan_info;
4541
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004542 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004543 (eConnectionState_Connecting ==
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004544 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004545 {
4546 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004547 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
4548 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004549 return -EBUSY;
4550 }
4551
Jeff Johnson295189b2012-06-20 16:38:30 -07004552#ifdef WLAN_BTAMP_FEATURE
4553 //Scan not supported when AMP traffic is on.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004554 if (VOS_TRUE == WLANBAP_AmpSessionOn())
Jeff Johnson295189b2012-06-20 16:38:30 -07004555 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004556 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004557 "%s: No scanning when AMP is on", __func__);
4558 return -EOPNOTSUPP;
4559 }
4560#endif
4561 //Scan on any other interface is not supported.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004562 if (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07004563 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004564 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004565 "%s: Not scanning on device_mode = %d",
4566 __func__, pAdapter->device_mode);
4567 return -EOPNOTSUPP;
4568 }
4569
4570 if (TRUE == pScanInfo->mScanPending)
4571 {
4572 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004573 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07004574 }
4575
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304576 //Don't Allow Scan and return busy if Remain On
Jeff Johnson32d95a32012-09-10 13:15:23 -07004577 //Channel and action frame is pending
4578 //Otherwise Cancel Remain On Channel and allow Scan
4579 //If no action frame pending
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004580 if (0 != wlan_hdd_check_remain_on_channel(pAdapter))
Jeff Johnson32d95a32012-09-10 13:15:23 -07004581 {
4582 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
4583 return -EBUSY;
4584 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004585#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004586 /* if tdls disagree scan right now, return immediately.
4587 tdls will schedule the scan when scan is allowed. (return SUCCESS)
4588 or will reject the scan if any TDLS is in progress. (return -EBUSY)
4589 */
4590 status = wlan_hdd_tdls_scan_callback (pAdapter,
4591 wiphy,
4592#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4593 dev,
Gopichand Nakkalac3c42b92013-03-20 19:42:34 -07004594#endif
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004595 request);
4596 if(status <= 0)
4597 {
4598 hddLog(VOS_TRACE_LEVEL_INFO, "%s: TDLS Pending %d", __func__, status);
4599 return status;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004600 }
4601#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07004602
Jeff Johnson295189b2012-06-20 16:38:30 -07004603 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
4604 {
4605 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08004606 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004607 return -EAGAIN;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304608 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004609 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
4610 {
4611 hddLog(VOS_TRACE_LEVEL_WARN,
4612 "%s: MAX TM Level Scan not allowed", __func__);
4613 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304614 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07004615 }
4616 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4617
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004618 /* Check if scan is allowed at this point of time.
4619 */
4620 if (!hdd_isScanAllowed(pHddCtx))
4621 {
4622 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
4623 return -EBUSY;
4624 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304625
Jeff Johnson295189b2012-06-20 16:38:30 -07004626 vos_mem_zero( &scanRequest, sizeof(scanRequest));
4627
4628 if (NULL != request)
4629 {
4630 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304631 (int)request->n_ssids);
Jeff Johnson295189b2012-06-20 16:38:30 -07004632
4633 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
4634 * Becasue of this, driver is assuming that this is not wildcard scan and so
4635 * is not aging out the scan results.
4636 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07004637 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07004638 {
4639 request->n_ssids = 0;
4640 }
4641
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004642 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07004643 {
4644 tCsrSSIDInfo *SsidInfo;
4645 int j;
4646 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
4647 /* Allocate num_ssid tCsrSSIDInfo structure */
4648 SsidInfo = scanRequest.SSIDs.SSIDList =
4649 ( tCsrSSIDInfo *)vos_mem_malloc(
4650 request->n_ssids*sizeof(tCsrSSIDInfo));
4651
4652 if(NULL == scanRequest.SSIDs.SSIDList)
4653 {
4654 hddLog(VOS_TRACE_LEVEL_ERROR,
4655 "memory alloc failed SSIDInfo buffer");
4656 return -ENOMEM;
4657 }
4658
4659 /* copy all the ssid's and their length */
4660 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
4661 {
4662 /* get the ssid length */
4663 SsidInfo->SSID.length = request->ssids[j].ssid_len;
4664 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
4665 SsidInfo->SSID.length);
4666 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
4667 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
4668 j, SsidInfo->SSID.ssId);
4669 }
4670 /* set the scan type to active */
4671 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4672 }
4673 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4674 {
4675 /* set the scan type to active */
4676 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4677 }
4678 else
4679 {
4680 /*Set the scan type to default type, in this case it is ACTIVE*/
4681 scanRequest.scanType = pScanInfo->scan_mode;
4682 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304683 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
Jeff Johnson295189b2012-06-20 16:38:30 -07004684 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4685 }
4686 else
4687 {
4688 /* set the scan type to active */
4689 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4690 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4691
4692 /* set min and max channel time to zero */
4693 scanRequest.minChnTime = 0;
4694 scanRequest.maxChnTime = 0;
4695 }
4696
4697 /* set BSSType to default type */
4698 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4699
4700 /*TODO: scan the requested channels only*/
4701
4702 /*Right now scanning all the channels */
4703 if( request )
4704 {
4705 if( request->n_channels )
4706 {
4707 channelList = vos_mem_malloc( request->n_channels );
4708 if( NULL == channelList )
4709 {
4710 status = -ENOMEM;
4711 goto free_mem;
4712 }
4713
4714 for( i = 0 ; i < request->n_channels ; i++ )
4715 channelList[i] = request->channels[i]->hw_value;
4716 }
4717
4718 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4719 scanRequest.ChannelInfo.ChannelList = channelList;
4720
4721 /* set requestType to full scan */
4722 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304723
4724 /* Flush the scan results(only p2p beacons) for STA scan and P2P
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004725 * search (Flush on both full scan and social scan but not on single
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304726 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004727 */
4728
4729 /* Supplicant does single channel scan after 8-way handshake
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304730 * and in that case driver shoudnt flush scan results. If
4731 * driver flushes the scan results here and unfortunately if
4732 * the AP doesnt respond to our probe req then association
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004733 * fails which is not desired
4734 */
4735
4736 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4737 {
4738 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4739 pAdapter->sessionId );
4740 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004741
4742 if( request->ie_len )
4743 {
4744 /* save this for future association (join requires this) */
4745 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4746 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4747 pScanInfo->scanAddIE.length = request->ie_len;
4748
4749 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004750 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4751 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004752 )
4753 {
4754 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4755 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4756 }
4757
4758 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4759 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4760
Jeff Johnson295189b2012-06-20 16:38:30 -07004761 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4762 request->ie_len);
4763 if (pP2pIe != NULL)
4764 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004765#ifdef WLAN_FEATURE_P2P_DEBUG
4766 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4767 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4768 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4769 {
4770 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4771 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4772 "Go nego completed to Connection is started");
4773 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4774 "for 8way Handshake");
4775 }
4776 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4777 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4778 {
4779 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4780 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4781 "Disconnected state to Connection is started");
4782 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4783 "for 4way Handshake");
4784 }
4785#endif
4786
Jeff Johnsone7245742012-09-05 17:12:55 -07004787 /* no_cck will be set during p2p find to disable 11b rates */
4788 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004789 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004790 hddLog(VOS_TRACE_LEVEL_INFO,
4791 "%s: This is a P2P Search", __func__);
4792 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004793
Jeff Johnsone7245742012-09-05 17:12:55 -07004794 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4795 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004796 /* set requestType to P2P Discovery */
4797 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004798 }
4799
4800 /*
4801 Skip Dfs Channel in case of P2P Search
4802 if it is set in ini file
4803 */
4804 if(cfg_param->skipDfsChnlInP2pSearch)
4805 {
4806 scanRequest.skipDfsChnlInP2pSearch = 1;
4807 }
4808 else
4809 {
4810 scanRequest.skipDfsChnlInP2pSearch = 0;
4811 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004812
Jeff Johnson295189b2012-06-20 16:38:30 -07004813 }
4814 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004815 }
4816 }
4817
4818 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4819
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004820 /* acquire the wakelock to avoid the apps suspend during the scan. To
4821 * address the following issues.
4822 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4823 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4824 * for long time, this result in apps running at full power for long time.
4825 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4826 * be stuck in full power because of resume BMPS
4827 */
4828 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004829
4830 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004831 pAdapter->sessionId, &scanRequest, &scanId,
4832 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004833
Jeff Johnson295189b2012-06-20 16:38:30 -07004834 if (eHAL_STATUS_SUCCESS != status)
4835 {
4836 hddLog(VOS_TRACE_LEVEL_ERROR,
4837 "%s: sme_ScanRequest returned error %d", __func__, status);
4838 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004839 if(eHAL_STATUS_RESOURCES == status)
4840 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004841 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 -07004842 status = -EBUSY;
4843 } else {
4844 status = -EIO;
4845 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004846 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004847 goto free_mem;
4848 }
4849
4850 pScanInfo->mScanPending = TRUE;
4851 pAdapter->request = request;
4852 pScanInfo->scanId = scanId;
4853
4854 complete(&pScanInfo->scan_req_completion_event);
4855
4856free_mem:
4857 if( scanRequest.SSIDs.SSIDList )
4858 {
4859 vos_mem_free(scanRequest.SSIDs.SSIDList);
4860 }
4861
4862 if( channelList )
4863 vos_mem_free( channelList );
4864
4865 EXIT();
4866
4867 return status;
4868}
4869
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07004870
4871void hdd_select_cbmode( hdd_adapter_t *pAdapter,v_U8_t operationChannel)
4872{
4873 v_U8_t iniDot11Mode =
4874 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->dot11Mode;
4875 eHddDot11Mode hddDot11Mode = iniDot11Mode;
4876
4877 switch ( iniDot11Mode )
4878 {
4879 case eHDD_DOT11_MODE_AUTO:
4880 case eHDD_DOT11_MODE_11ac:
4881 case eHDD_DOT11_MODE_11ac_ONLY:
4882#ifdef WLAN_FEATURE_11AC
4883 hddDot11Mode = eHDD_DOT11_MODE_11ac;
4884#else
4885 hddDot11Mode = eHDD_DOT11_MODE_11n;
4886#endif
4887 break;
4888 case eHDD_DOT11_MODE_11n:
4889 case eHDD_DOT11_MODE_11n_ONLY:
4890 hddDot11Mode = eHDD_DOT11_MODE_11n;
4891 break;
4892 default:
4893 hddDot11Mode = iniDot11Mode;
4894 break;
4895 }
4896 /* This call decides required channel bonding mode */
4897 sme_SelectCBMode((WLAN_HDD_GET_CTX(pAdapter)->hHal),
4898 hdd_cfg_xlate_to_csr_phy_mode(hddDot11Mode),
4899 operationChannel);
4900}
4901
Jeff Johnson295189b2012-06-20 16:38:30 -07004902/*
4903 * FUNCTION: wlan_hdd_cfg80211_connect_start
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304904 * This function is used to start the association process
Jeff Johnson295189b2012-06-20 16:38:30 -07004905 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304906int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004907 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004908{
4909 int status = 0;
4910 hdd_wext_state_t *pWextState;
4911 v_U32_t roamId;
4912 tCsrRoamProfile *pRoamProfile;
4913 eMib_dot11DesiredBssType connectedBssType;
4914 eCsrAuthType RSNAuthType;
4915
4916 ENTER();
4917
4918 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304919
Jeff Johnson295189b2012-06-20 16:38:30 -07004920 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4921 {
4922 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4923 return -EINVAL;
4924 }
4925
4926 pRoamProfile = &pWextState->roamProfile;
4927
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304928 if (pRoamProfile)
Jeff Johnson295189b2012-06-20 16:38:30 -07004929 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004930 int ret = 0;
4931 hdd_station_ctx_t *pHddStaCtx;
4932 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4933 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4934
4935 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4936 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4937 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004938 {
4939 /* Issue disconnect to CSR */
4940 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304941 if( eHAL_STATUS_SUCCESS ==
Jeff Johnson295189b2012-06-20 16:38:30 -07004942 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4943 pAdapter->sessionId,
4944 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4945 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004946 ret = wait_for_completion_interruptible_timeout(
4947 &pAdapter->disconnect_comp_var,
4948 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4949 if (0 == ret)
4950 {
4951 VOS_ASSERT(0);
4952 }
4953 }
4954 }
4955 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4956 {
4957 ret = wait_for_completion_interruptible_timeout(
4958 &pAdapter->disconnect_comp_var,
4959 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4960 if (0 == ret)
4961 {
4962 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004963 }
4964 }
4965
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304966 if (HDD_WMM_USER_MODE_NO_QOS ==
Jeff Johnson295189b2012-06-20 16:38:30 -07004967 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4968 {
4969 /*QoS not enabled in cfg file*/
4970 pRoamProfile->uapsd_mask = 0;
4971 }
4972 else
4973 {
4974 /*QoS enabled, update uapsd mask from cfg file*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304975 pRoamProfile->uapsd_mask =
Jeff Johnson295189b2012-06-20 16:38:30 -07004976 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4977 }
4978
4979 pRoamProfile->SSIDs.numOfSSIDs = 1;
4980 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4981 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304982 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Jeff Johnson295189b2012-06-20 16:38:30 -07004983 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4984 ssid, ssid_len);
4985
4986 if (bssid)
4987 {
4988 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4989 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4990 WNI_CFG_BSSID_LEN);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304991 /* Save BSSID in seperate variable as well, as RoamProfile
4992 BSSID is getting zeroed out in the association process. And in
Jeff Johnson295189b2012-06-20 16:38:30 -07004993 case of join failure we should send valid BSSID to supplicant
4994 */
4995 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4996 WNI_CFG_BSSID_LEN);
4997 }
Dhanashri Atre51981c62013-06-13 11:47:57 -07004998 else
4999 {
5000 vos_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),WNI_CFG_BSSID_LEN);
5001 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005002
5003 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
5004 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305005 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005006 /*set gen ie*/
5007 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
5008 /*set auth*/
5009 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
5010 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005011#ifdef FEATURE_WLAN_WAPI
5012 if (pAdapter->wapi_info.nWapiMode)
5013 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005014 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005015 switch (pAdapter->wapi_info.wapiAuthMode)
5016 {
5017 case WAPI_AUTH_MODE_PSK:
5018 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005019 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07005020 pAdapter->wapi_info.wapiAuthMode);
5021 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
5022 break;
5023 }
5024 case WAPI_AUTH_MODE_CERT:
5025 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005026 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07005027 pAdapter->wapi_info.wapiAuthMode);
5028 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
5029 break;
5030 }
5031 } // End of switch
5032 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
5033 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
5034 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005035 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005036 pRoamProfile->AuthType.numEntries = 1;
5037 pRoamProfile->EncryptionType.numEntries = 1;
5038 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
5039 pRoamProfile->mcEncryptionType.numEntries = 1;
5040 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
5041 }
5042 }
5043#endif /* FEATURE_WLAN_WAPI */
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05305044#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05305045 /* Initializing gtkOffloadReqParams */
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05305046 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5047 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
5048 {
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05305049 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
5050 sizeof (tSirGtkOffloadParams));
5051 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05305052 }
5053#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005054 pRoamProfile->csrPersona = pAdapter->device_mode;
5055
Jeff Johnson32d95a32012-09-10 13:15:23 -07005056 if( operatingChannel )
5057 {
5058 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
5059 pRoamProfile->ChannelInfo.numOfChannels = 1;
5060 }
Chet Lanctot186b5732013-03-18 10:26:30 -07005061 else
5062 {
5063 pRoamProfile->ChannelInfo.ChannelList = NULL;
5064 pRoamProfile->ChannelInfo.numOfChannels = 0;
5065 }
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07005066 if ( (WLAN_HDD_IBSS == pAdapter->device_mode) && operatingChannel)
5067 {
5068 hdd_select_cbmode(pAdapter,operatingChannel);
5069 }
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005070 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
5071 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305072 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005073 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08005074 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
5075 */
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305076 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
5077 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08005078 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
5079 eConnectionState_Connecting);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305080
5081 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07005082 pAdapter->sessionId, pRoamProfile, &roamId);
5083
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305084 if ((eHAL_STATUS_SUCCESS != status) &&
5085 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
5086 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05305087
5088 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005089 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
5090 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
5091 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05305092 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005093 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05305094 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08005095
5096 pRoamProfile->ChannelInfo.ChannelList = NULL;
5097 pRoamProfile->ChannelInfo.numOfChannels = 0;
5098
Jeff Johnson295189b2012-06-20 16:38:30 -07005099 }
5100 else
5101 {
5102 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
5103 return -EINVAL;
5104 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08005105 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005106 return status;
5107}
5108
5109/*
5110 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
5111 * This function is used to set the authentication type (OPEN/SHARED).
5112 *
5113 */
5114static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
5115 enum nl80211_auth_type auth_type)
5116{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305117 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005118 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5119
5120 ENTER();
5121
5122 /*set authentication type*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305123 switch (auth_type)
Jeff Johnson295189b2012-06-20 16:38:30 -07005124 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005125 case NL80211_AUTHTYPE_AUTOMATIC:
Gopichand Nakkala29149562013-05-10 21:43:41 +05305126 hddLog(VOS_TRACE_LEVEL_INFO,
5127 "%s: set authentication type to AUTOSWITCH", __func__);
5128 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
5129 break;
5130
5131 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07005132#ifdef WLAN_FEATURE_VOWIFI_11R
5133 case NL80211_AUTHTYPE_FT:
5134#endif /* WLAN_FEATURE_VOWIFI_11R */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305135 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07005136 "%s: set authentication type to OPEN", __func__);
5137 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5138 break;
5139
5140 case NL80211_AUTHTYPE_SHARED_KEY:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305141 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07005142 "%s: set authentication type to SHARED", __func__);
5143 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
5144 break;
5145#ifdef FEATURE_WLAN_CCX
5146 case NL80211_AUTHTYPE_NETWORK_EAP:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305147 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07005148 "%s: set authentication type to CCKM WPA", __func__);
5149 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
5150 break;
5151#endif
5152
5153
5154 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305155 hddLog(VOS_TRACE_LEVEL_ERROR,
5156 "%s: Unsupported authentication type %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07005157 auth_type);
5158 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
5159 return -EINVAL;
5160 }
5161
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305162 pWextState->roamProfile.AuthType.authType[0] =
Jeff Johnson295189b2012-06-20 16:38:30 -07005163 pHddStaCtx->conn_info.authType;
5164 return 0;
5165}
5166
5167/*
5168 * FUNCTION: wlan_hdd_set_akm_suite
5169 * This function is used to set the key mgmt type(PSK/8021x).
5170 *
5171 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305172static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07005173 u32 key_mgmt
5174 )
5175{
5176 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5177 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305178
Jeff Johnson295189b2012-06-20 16:38:30 -07005179 /*set key mgmt type*/
5180 switch(key_mgmt)
5181 {
5182 case WLAN_AKM_SUITE_PSK:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05305183#ifdef WLAN_FEATURE_VOWIFI_11R
5184 case WLAN_AKM_SUITE_FT_PSK:
5185#endif
5186 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
Jeff Johnson295189b2012-06-20 16:38:30 -07005187 __func__);
5188 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
5189 break;
5190
5191 case WLAN_AKM_SUITE_8021X:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05305192#ifdef WLAN_FEATURE_VOWIFI_11R
5193 case WLAN_AKM_SUITE_FT_8021X:
5194#endif
5195 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
Jeff Johnson295189b2012-06-20 16:38:30 -07005196 __func__);
5197 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
5198 break;
5199#ifdef FEATURE_WLAN_CCX
5200#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
5201#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
5202 case WLAN_AKM_SUITE_CCKM:
5203 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
5204 __func__);
5205 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
5206 break;
5207#endif
5208
5209 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305210 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005211 __func__, key_mgmt);
5212 return -EINVAL;
5213
5214 }
5215 return 0;
5216}
5217
5218/*
5219 * FUNCTION: wlan_hdd_cfg80211_set_cipher
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305220 * This function is used to set the encryption type
Jeff Johnson295189b2012-06-20 16:38:30 -07005221 * (NONE/WEP40/WEP104/TKIP/CCMP).
5222 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305223static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
5224 u32 cipher,
Jeff Johnson295189b2012-06-20 16:38:30 -07005225 bool ucast
5226 )
5227{
5228 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305229 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005230 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5231
5232 ENTER();
5233
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305234 if (!cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07005235 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305236 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
Jeff Johnson295189b2012-06-20 16:38:30 -07005237 __func__, cipher);
5238 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5239 }
5240 else
5241 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305242
Jeff Johnson295189b2012-06-20 16:38:30 -07005243 /*set encryption method*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305244 switch (cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07005245 {
5246 case IW_AUTH_CIPHER_NONE:
5247 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5248 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305249
Jeff Johnson295189b2012-06-20 16:38:30 -07005250 case WLAN_CIPHER_SUITE_WEP40:
Gopichand Nakkala29149562013-05-10 21:43:41 +05305251 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
Jeff Johnson295189b2012-06-20 16:38:30 -07005252 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305253
Jeff Johnson295189b2012-06-20 16:38:30 -07005254 case WLAN_CIPHER_SUITE_WEP104:
Gopichand Nakkala29149562013-05-10 21:43:41 +05305255 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
Jeff Johnson295189b2012-06-20 16:38:30 -07005256 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305257
Jeff Johnson295189b2012-06-20 16:38:30 -07005258 case WLAN_CIPHER_SUITE_TKIP:
5259 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5260 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305261
Jeff Johnson295189b2012-06-20 16:38:30 -07005262 case WLAN_CIPHER_SUITE_CCMP:
5263 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5264 break;
5265#ifdef FEATURE_WLAN_WAPI
5266 case WLAN_CIPHER_SUITE_SMS4:
5267 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
5268 break;
5269#endif
5270
5271#ifdef FEATURE_WLAN_CCX
5272 case WLAN_CIPHER_SUITE_KRK:
5273 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
5274 break;
5275#endif
5276 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305277 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005278 __func__, cipher);
5279 return -EOPNOTSUPP;
5280 }
5281 }
5282
5283 if (ucast)
5284 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305285 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005286 __func__, encryptionType);
5287 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5288 pWextState->roamProfile.EncryptionType.numEntries = 1;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305289 pWextState->roamProfile.EncryptionType.encryptionType[0] =
Jeff Johnson295189b2012-06-20 16:38:30 -07005290 encryptionType;
5291 }
5292 else
5293 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305294 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005295 __func__, encryptionType);
5296 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
5297 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
5298 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
5299 }
5300
5301 return 0;
5302}
5303
5304
5305/*
5306 * FUNCTION: wlan_hdd_cfg80211_set_ie
5307 * This function is used to parse WPA/RSN IE's.
5308 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305309int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
5310 u8 *ie,
Jeff Johnson295189b2012-06-20 16:38:30 -07005311 size_t ie_len
5312 )
5313{
5314 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5315 u8 *genie = ie;
5316 v_U16_t remLen = ie_len;
5317#ifdef FEATURE_WLAN_WAPI
5318 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
5319 u16 *tmp;
5320 v_U16_t akmsuiteCount;
5321 int *akmlist;
5322#endif
5323 ENTER();
5324
5325 /* clear previous assocAddIE */
5326 pWextState->assocAddIE.length = 0;
5327 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
5328
5329 while (remLen >= 2)
5330 {
5331 v_U16_t eLen = 0;
5332 v_U8_t elementId;
5333 elementId = *genie++;
5334 eLen = *genie++;
5335 remLen -= 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305336
5337 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07005338 __func__, elementId, eLen);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305339
5340 switch ( elementId )
Jeff Johnson295189b2012-06-20 16:38:30 -07005341 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305342 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005343 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 -07005344 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305345 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005346 "%s: Invalid WPA IE", __func__);
5347 return -EINVAL;
5348 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305349 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
Jeff Johnson295189b2012-06-20 16:38:30 -07005350 {
5351 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305352 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
Jeff Johnson295189b2012-06-20 16:38:30 -07005353 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305354
Jeff Johnson295189b2012-06-20 16:38:30 -07005355 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5356 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005357 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
5358 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005359 VOS_ASSERT(0);
5360 return -ENOMEM;
5361 }
5362 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5363 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5364 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305365
Jeff Johnson295189b2012-06-20 16:38:30 -07005366 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
5367 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5368 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5369 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305370 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
5371 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005372 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
5373 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5374 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
5375 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
5376 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
5377 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305378 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
5379 P2P_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07005380 /*Consider P2P IE, only for P2P Client */
5381 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5382 {
5383 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305384 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
Jeff Johnson295189b2012-06-20 16:38:30 -07005385 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305386
Jeff Johnson295189b2012-06-20 16:38:30 -07005387 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5388 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005389 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5390 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005391 VOS_ASSERT(0);
5392 return -ENOMEM;
5393 }
5394 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5395 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5396 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305397
Jeff Johnson295189b2012-06-20 16:38:30 -07005398 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5399 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5400 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005401#ifdef WLAN_FEATURE_WFD
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305402 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
5403 WFD_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07005404 /*Consider WFD IE, only for P2P Client */
5405 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5406 {
5407 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305408 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
Jeff Johnson295189b2012-06-20 16:38:30 -07005409 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305410
Jeff Johnson295189b2012-06-20 16:38:30 -07005411 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5412 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005413 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5414 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005415 VOS_ASSERT(0);
5416 return -ENOMEM;
5417 }
5418 // WFD IE is saved to Additional IE ; it should be accumulated to handle
5419 // WPS IE + P2P IE + WFD IE
5420 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5421 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305422
Jeff Johnson295189b2012-06-20 16:38:30 -07005423 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5424 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5425 }
5426#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005427 /* Appending HS 2.0 Indication Element in Assiciation Request */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305428 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005429 HS20_OUI_TYPE_SIZE)) )
5430 {
5431 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305432 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005433 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005434
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005435 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5436 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005437 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5438 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005439 VOS_ASSERT(0);
5440 return -ENOMEM;
5441 }
5442 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5443 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005444
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005445 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5446 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5447 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005448
Praveen Kumar Sirisilla7d68b7b2013-09-22 14:01:42 -07005449 if (WLAN_HDD_IBSS == pAdapter->device_mode) {
5450
5451 /* populating as ADDIE in beacon frames */
5452 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
5453 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie - 2, eLen + 2,
5454 NULL, eANI_BOOLEAN_FALSE)== eHAL_STATUS_SUCCESS)
5455 {
5456 if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter),
5457 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
5458 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
5459 {
5460 hddLog(LOGE,
5461 "Coldn't pass "
5462 "WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
5463 }
5464 }/* ccmCfgSetStr(,WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, , )*/
5465 else
5466 hddLog(LOGE,
5467 "Could not pass on "
5468 "WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
5469
5470 /* IBSS mode doesn't contain params->proberesp_ies still
5471 beaconIE's need to be populated in probe response frames */
5472 if ( (NULL != (genie - 2)) && (0 != eLen + 2) )
5473 {
5474 u16 rem_probe_resp_ie_len = eLen + 2;
5475 u8 probe_rsp_ie_len[3] = {0};
5476 u8 counter = 0;
5477
5478 /* Check Probe Resp Length if it is greater then 255 then
5479 Store Probe Rsp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1
5480 & WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are
5481 not able Store More then 255 bytes into One Variable */
5482
5483 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
5484 {
5485 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
5486 {
5487 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
5488 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
5489 }
5490 else
5491 {
5492 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
5493 rem_probe_resp_ie_len = 0;
5494 }
5495 }
5496
5497 rem_probe_resp_ie_len = 0;
5498
5499 if (probe_rsp_ie_len[0] > 0)
5500 {
5501 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
5502 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
5503 (tANI_U8*)(genie - 2),
5504 probe_rsp_ie_len[0], NULL,
5505 eANI_BOOLEAN_FALSE)
5506 == eHAL_STATUS_FAILURE)
5507 {
5508 hddLog(LOGE,
5509 "Could not pass"
5510 "on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
5511 }
5512 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
5513 }
5514
5515 if (probe_rsp_ie_len[1] > 0)
5516 {
5517 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
5518 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
5519 (tANI_U8*)(genie - (2 + rem_probe_resp_ie_len)),
5520 probe_rsp_ie_len[1], NULL,
5521 eANI_BOOLEAN_FALSE)
5522 == eHAL_STATUS_FAILURE)
5523 {
5524 hddLog(LOGE,
5525 "Could not pass"
5526 "on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
5527 }
5528 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
5529 }
5530
5531 if (probe_rsp_ie_len[2] > 0)
5532 {
5533 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
5534 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
5535 (tANI_U8*)(genie - (2 + rem_probe_resp_ie_len)),
5536 probe_rsp_ie_len[2], NULL,
5537 eANI_BOOLEAN_FALSE)
5538 == eHAL_STATUS_FAILURE)
5539 {
5540 hddLog(LOGE,
5541 "Could not pass"
5542 "on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
5543 }
5544 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
5545 }
5546
5547 if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter),
5548 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
5549 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
5550 {
5551 hddLog(LOGE,
5552 "Could not pass"
5553 "on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
5554 }
5555 }
5556 else
5557 {
5558 // Reset WNI_CFG_PROBE_RSP Flags
5559 wlan_hdd_reset_prob_rspies(pAdapter);
5560
5561 hddLog(VOS_TRACE_LEVEL_INFO,
5562 "%s: No Probe Response IE received in set beacon",
5563 __func__);
5564 }
5565 } /* end of if (WLAN_HDD_IBSS == pAdapter->device_mode) */
Jeff Johnson295189b2012-06-20 16:38:30 -07005566 break;
5567 case DOT11F_EID_RSN:
5568 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
5569 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5570 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
5571 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
5572 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
5573 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005574 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
5575 case DOT11F_EID_EXTCAP:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305576 {
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005577 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305578 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005579 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305580
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005581 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5582 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005583 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5584 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005585 VOS_ASSERT(0);
5586 return -ENOMEM;
5587 }
5588 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5589 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305590
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005591 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5592 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5593 break;
5594 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005595#ifdef FEATURE_WLAN_WAPI
5596 case WLAN_EID_WAPI:
5597 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
5598 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
5599 pAdapter->wapi_info.nWapiMode);
5600 tmp = (u16 *)ie;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305601 tmp = tmp + 2; // Skip element Id and Len, Version
Jeff Johnson295189b2012-06-20 16:38:30 -07005602 akmsuiteCount = WPA_GET_LE16(tmp);
5603 tmp = tmp + 1;
5604 akmlist = (int *)(tmp);
5605 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
5606 {
5607 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
5608 }
5609 else
5610 {
5611 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
5612 VOS_ASSERT(0);
5613 return -EINVAL;
5614 }
5615
5616 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
5617 {
5618 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005619 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005620 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305621 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005622 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305623 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005624 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005625 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005626 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
5627 }
5628 break;
5629#endif
5630 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305631 hddLog (VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005632 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005633 /* when Unknown IE is received we should break and continue
5634 * to the next IE in the buffer instead we were returning
5635 * so changing this to break */
5636 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005637 }
5638 genie += eLen;
5639 remLen -= eLen;
5640 }
5641 EXIT();
5642 return 0;
5643}
5644
5645/*
Gopichand Nakkala18f0c262013-05-07 23:25:08 +05305646 * FUNCTION: hdd_isWPAIEPresent
5647 * Parse the received IE to find the WPA IE
5648 *
5649 */
5650static bool hdd_isWPAIEPresent(u8 *ie, u8 ie_len)
5651{
5652 v_U8_t eLen = 0;
5653 v_U16_t remLen = ie_len;
5654 v_U8_t elementId = 0;
5655
5656 while (remLen >= 2)
5657 {
5658 elementId = *ie++;
5659 eLen = *ie++;
5660 remLen -= 2;
5661 if (eLen > remLen)
5662 {
5663 hddLog(VOS_TRACE_LEVEL_ERROR,
5664 "%s: IE length is wrong %d", __func__, eLen);
5665 return FALSE;
5666 }
5667 if ((elementId == DOT11F_EID_WPA) && (remLen > 5))
5668 {
5669 /* OUI - 0x00 0X50 0XF2
5670 WPA Information Element - 0x01
5671 WPA version - 0x01*/
5672 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
5673 return TRUE;
5674 }
5675 ie += eLen;
5676 remLen -= eLen;
5677 }
5678 return FALSE;
5679}
5680
5681/*
Jeff Johnson295189b2012-06-20 16:38:30 -07005682 * FUNCTION: wlan_hdd_cfg80211_set_privacy
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305683 * This function is used to initialize the security
Jeff Johnson295189b2012-06-20 16:38:30 -07005684 * parameters during connect operation.
5685 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305686int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07005687 struct cfg80211_connect_params *req
5688 )
5689{
5690 int status = 0;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305691 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005692 ENTER();
5693
5694 /*set wpa version*/
5695 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5696
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305697 if (req->crypto.wpa_versions)
Jeff Johnson295189b2012-06-20 16:38:30 -07005698 {
Gopichand Nakkala781ded42013-06-28 12:10:45 +05305699 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
Jeff Johnson295189b2012-06-20 16:38:30 -07005700 {
5701 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5702 }
5703 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
5704 {
5705 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5706 }
5707 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305708
5709 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07005710 pWextState->wpaVersion);
5711
5712 /*set authentication type*/
5713 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
5714
5715 if (0 > status)
5716 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305717 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005718 "%s: failed to set authentication type ", __func__);
5719 return status;
5720 }
5721
5722 /*set key mgmt type*/
5723 if (req->crypto.n_akm_suites)
5724 {
5725 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
5726 if (0 > status)
5727 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305728 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
Jeff Johnson295189b2012-06-20 16:38:30 -07005729 __func__);
5730 return status;
5731 }
5732 }
5733
5734 /*set pairwise cipher type*/
5735 if (req->crypto.n_ciphers_pairwise)
5736 {
5737 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
5738 req->crypto.ciphers_pairwise[0], true);
5739 if (0 > status)
5740 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305741 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005742 "%s: failed to set unicast cipher type", __func__);
5743 return status;
5744 }
5745 }
5746 else
5747 {
5748 /*Reset previous cipher suite to none*/
5749 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
5750 if (0 > status)
5751 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305752 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005753 "%s: failed to set unicast cipher type", __func__);
5754 return status;
5755 }
5756 }
5757
5758 /*set group cipher type*/
5759 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
5760 false);
5761
5762 if (0 > status)
5763 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305764 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
Jeff Johnson295189b2012-06-20 16:38:30 -07005765 __func__);
5766 return status;
5767 }
5768
Chet Lanctot186b5732013-03-18 10:26:30 -07005769#ifdef WLAN_FEATURE_11W
5770 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
5771#endif
5772
Jeff Johnson295189b2012-06-20 16:38:30 -07005773 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
5774 if (req->ie_len)
5775 {
5776 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
5777 if ( 0 > status)
5778 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305779 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
Jeff Johnson295189b2012-06-20 16:38:30 -07005780 __func__);
5781 return status;
5782 }
5783 }
5784
5785 /*incase of WEP set default key information*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305786 if (req->key && req->key_len)
Jeff Johnson295189b2012-06-20 16:38:30 -07005787 {
5788 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
5789 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
5790 )
5791 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305792 if ( IW_AUTH_KEY_MGMT_802_1X
Jeff Johnson295189b2012-06-20 16:38:30 -07005793 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
5794 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305795 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
Jeff Johnson295189b2012-06-20 16:38:30 -07005796 __func__);
5797 return -EOPNOTSUPP;
5798 }
5799 else
5800 {
5801 u8 key_len = req->key_len;
5802 u8 key_idx = req->key_idx;
5803
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305804 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
Jeff Johnson295189b2012-06-20 16:38:30 -07005805 && (CSR_MAX_NUM_KEY > key_idx)
5806 )
5807 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305808 hddLog(VOS_TRACE_LEVEL_INFO,
5809 "%s: setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07005810 __func__, key_idx, key_len);
5811 vos_mem_copy(
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305812 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07005813 req->key, key_len);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305814 pWextState->roamProfile.Keys.KeyLength[key_idx] =
Jeff Johnson295189b2012-06-20 16:38:30 -07005815 (u8)key_len;
5816 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
5817 }
5818 }
5819 }
5820 }
5821
5822 return status;
5823}
5824
5825/*
5826 * FUNCTION: wlan_hdd_cfg80211_set_privacy
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305827 * This function is used to initialize the security
Jeff Johnson295189b2012-06-20 16:38:30 -07005828 * parameters during connect operation.
5829 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305830static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07005831 struct net_device *ndev,
5832 struct cfg80211_connect_params *req
5833 )
5834{
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305835 int status;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305836 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07005837 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
5838 hdd_context_t *pHddCtx = NULL;
5839
5840 ENTER();
5841
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305842 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07005843 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5844
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305845 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5846 status = wlan_hdd_validate_context(pHddCtx);
5847
5848 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07005849 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305850 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5851 "%s: HDD context is not valid", __func__);
5852 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07005853 }
5854
5855#ifdef WLAN_BTAMP_FEATURE
5856 //Infra connect not supported when AMP traffic is on.
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305857 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
Jeff Johnson295189b2012-06-20 16:38:30 -07005858 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305859 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005860 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005861 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07005862 }
5863#endif
5864 /*initialise security parameters*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305865 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
Jeff Johnson295189b2012-06-20 16:38:30 -07005866
5867 if ( 0 > status)
5868 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305869 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
Jeff Johnson295189b2012-06-20 16:38:30 -07005870 __func__);
5871 return status;
5872 }
5873
5874 //If Device Mode is Station Concurrent Sessions Exit BMps
Jeff Johnsona8a1a482012-12-12 16:49:33 -08005875 //P2P Mode will be taken care in Open/close adapter
Jeff Johnson295189b2012-06-20 16:38:30 -07005876 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
5877 (vos_concurrent_sessions_running()))
5878 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305879 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
Jeff Johnson295189b2012-06-20 16:38:30 -07005880 }
5881
Mohit Khanna765234a2012-09-11 15:08:35 -07005882 if ( req->channel )
5883 {
5884 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5885 req->ssid_len, req->bssid,
5886 req->channel->hw_value);
5887 }
5888 else
5889 {
5890 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305891 req->ssid_len, req->bssid, 0);
Mohit Khanna765234a2012-09-11 15:08:35 -07005892 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005893
5894 if (0 > status)
5895 {
5896 //ReEnable BMPS if disabled
5897 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5898 (NULL != pHddCtx))
5899 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305900 if (pHddCtx->hdd_wlan_suspended)
5901 {
5902 hdd_set_pwrparams(pHddCtx);
5903 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005904 //ReEnable Bmps and Imps back
5905 hdd_enable_bmps_imps(pHddCtx);
5906 }
5907
5908 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5909 return status;
5910 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305911 pHddCtx->isAmpAllowed = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005912 EXIT();
5913 return status;
5914}
5915
5916
5917/*
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05305918 * FUNCTION: wlan_hdd_disconnect
5919 * This function is used to issue a disconnect request to SME
5920 */
5921int wlan_hdd_disconnect( hdd_adapter_t *pAdapter, u16 reason )
5922{
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305923 int status;
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05305924 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305925 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5926
5927 status = wlan_hdd_validate_context(pHddCtx);
5928
5929 if (0 != status)
5930 {
5931 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5932 "%s: HDD context is not valid", __func__);
5933 return status;
5934 }
5935
5936 pHddCtx->isAmpAllowed = VOS_TRUE;
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05305937 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05305938 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305939
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05305940 /*issue disconnect*/
5941 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5942 pAdapter->sessionId, reason);
5943
5944 if ( 0 != status )
5945 {
5946 hddLog(VOS_TRACE_LEVEL_ERROR,
5947 "%s csrRoamDisconnect failure, returned %d \n",
5948 __func__, (int)status );
5949 return -EINVAL;
5950 }
5951 wait_for_completion_interruptible_timeout(
5952 &pAdapter->disconnect_comp_var,
5953 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5954 /*stop tx queues*/
5955 netif_tx_disable(pAdapter->dev);
5956 netif_carrier_off(pAdapter->dev);
5957 return status;
5958}
5959
5960
5961/*
Jeff Johnson295189b2012-06-20 16:38:30 -07005962 * FUNCTION: wlan_hdd_cfg80211_disconnect
5963 * This function is used to issue a disconnect request to SME
5964 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305965static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07005966 struct net_device *dev,
5967 u16 reason
5968 )
5969{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305970 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5971 tCsrRoamProfile *pRoamProfile =
Jeff Johnson295189b2012-06-20 16:38:30 -07005972 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305973 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07005974 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005975 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05305976#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005977 tANI_U8 staIdx;
5978#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305979
Jeff Johnson295189b2012-06-20 16:38:30 -07005980 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305981
5982 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07005983 __func__,pAdapter->device_mode);
5984
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305985 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5986 __func__, reason);
Jeff Johnson295189b2012-06-20 16:38:30 -07005987
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305988 status = wlan_hdd_validate_context(pHddCtx);
5989
5990 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07005991 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305992 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5993 "%s: HDD context is not valid", __func__);
5994 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07005995 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305996
Jeff Johnson295189b2012-06-20 16:38:30 -07005997 if (NULL != pRoamProfile)
5998 {
5999 /*issue disconnect request to SME, if station is in connected state*/
6000 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
6001 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306002 eCsrRoamDisconnectReason reasonCode =
Jeff Johnson295189b2012-06-20 16:38:30 -07006003 eCSR_DISCONNECT_REASON_UNSPECIFIED;
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05306004 hdd_scaninfo_t *pScanInfo;
Jeff Johnson295189b2012-06-20 16:38:30 -07006005 switch(reason)
6006 {
6007 case WLAN_REASON_MIC_FAILURE:
6008 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
6009 break;
6010
6011 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
6012 case WLAN_REASON_DISASSOC_AP_BUSY:
6013 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
6014 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
6015 break;
6016
6017 case WLAN_REASON_PREV_AUTH_NOT_VALID:
6018 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
6019 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
6020 break;
6021
6022 case WLAN_REASON_DEAUTH_LEAVING:
6023 default:
6024 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
6025 break;
6026 }
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05306027 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6028 pScanInfo = &pHddCtx->scan_info;
6029 if (pScanInfo->mScanPending)
6030 {
6031 hddLog(VOS_TRACE_LEVEL_INFO, "Disconnect is in progress, "
6032 "Aborting Scan");
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05306033 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05306034 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006035
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006036#ifdef FEATURE_WLAN_TDLS
6037 /* First clean up the tdls peers if any */
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006038 for (staIdx = 0 ; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006039 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006040 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId == pAdapter->sessionId) &&
6041 (pHddCtx->tdlsConnInfo[staIdx].staId))
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006042 {
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006043 uint8 *mac;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006044 mac = pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006045 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006046 "%s: call sme_DeleteTdlsPeerSta staId %d sessionId %d " MAC_ADDRESS_STR,
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006047 __func__, pHddCtx->tdlsConnInfo[staIdx].staId, pAdapter->sessionId,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006048 MAC_ADDR_ARRAY(mac));
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006049 sme_DeleteTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006050 pAdapter->sessionId,
6051 mac);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006052 }
6053 }
6054#endif
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306055 status = wlan_hdd_disconnect(pAdapter, reasonCode);
6056 if ( 0 != status )
Jeff Johnson295189b2012-06-20 16:38:30 -07006057 {
6058 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306059 "%s wlan_hdd_disconnect failure, returned %d \n",
Jeff Johnson295189b2012-06-20 16:38:30 -07006060 __func__, (int)status );
6061 return -EINVAL;
6062 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006063 }
6064 }
6065 else
6066 {
6067 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
6068 }
6069
6070 return status;
6071}
6072
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306073
Jeff Johnson295189b2012-06-20 16:38:30 -07006074/*
6075 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306076 * This function is used to initialize the security
Jeff Johnson295189b2012-06-20 16:38:30 -07006077 * settings in IBSS mode.
6078 */
6079static int wlan_hdd_cfg80211_set_privacy_ibss(
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306080 hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07006081 struct cfg80211_ibss_params *params
6082 )
6083{
6084 int status = 0;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306085 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006086 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
6087 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306088
Jeff Johnson295189b2012-06-20 16:38:30 -07006089 ENTER();
6090
6091 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
6092
6093 if (params->ie_len && ( NULL != params->ie) )
6094 {
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006095 if (wlan_hdd_cfg80211_get_ie_ptr (params->ie,
6096 params->ie_len, WLAN_EID_RSN ))
Jeff Johnson295189b2012-06-20 16:38:30 -07006097 {
6098 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
6099 encryptionType = eCSR_ENCRYPT_TYPE_AES;
6100 }
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006101 else if ( hdd_isWPAIEPresent (params->ie, params->ie_len ))
Jeff Johnson295189b2012-06-20 16:38:30 -07006102 {
Shailender Karmuchi642e9812013-05-30 14:34:49 -07006103 tDot11fIEWPA dot11WPAIE;
6104 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006105 u8 *ie;
Shailender Karmuchi642e9812013-05-30 14:34:49 -07006106
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006107 ie = wlan_hdd_cfg80211_get_ie_ptr (params->ie,
6108 params->ie_len, DOT11F_EID_WPA);
6109 if ( NULL != ie )
6110 {
6111 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
6112 // Unpack the WPA IE
6113 //Skip past the EID byte and length byte - and four byte WiFi OUI
6114 dot11fUnpackIeWPA((tpAniSirGlobal) halHandle,
6115 &ie[2+4],
6116 ie[1] - 4,
6117 &dot11WPAIE);
6118 /*Extract the multicast cipher, the encType for unicast
6119 cipher for wpa-none is none*/
6120 encryptionType =
6121 hdd_TranslateWPAToCsrEncryptionType(dot11WPAIE.multicast_cipher);
6122 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006123 }
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006124
Jeff Johnson295189b2012-06-20 16:38:30 -07006125 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
6126
6127 if (0 > status)
6128 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306129 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
Jeff Johnson295189b2012-06-20 16:38:30 -07006130 __func__);
6131 return status;
6132 }
6133 }
6134
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306135 pWextState->roamProfile.AuthType.authType[0] =
6136 pHddStaCtx->conn_info.authType =
Jeff Johnson295189b2012-06-20 16:38:30 -07006137 eCSR_AUTH_TYPE_OPEN_SYSTEM;
6138
6139 if (params->privacy)
6140 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306141 /* Security enabled IBSS, At this time there is no information available
6142 * about the security paramters, so initialise the encryption type to
Jeff Johnson295189b2012-06-20 16:38:30 -07006143 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306144 * The correct security parameters will be updated later in
Jeff Johnson295189b2012-06-20 16:38:30 -07006145 * wlan_hdd_cfg80211_add_key */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306146 /* Hal expects encryption type to be set inorder
Jeff Johnson295189b2012-06-20 16:38:30 -07006147 *enable privacy bit in beacons */
6148
6149 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
6150 }
Shailender Karmuchi642e9812013-05-30 14:34:49 -07006151 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
6152 "encryptionType=%d", encryptionType);
Jeff Johnson295189b2012-06-20 16:38:30 -07006153 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
6154 pWextState->roamProfile.EncryptionType.numEntries = 1;
6155 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
Jeff Johnson295189b2012-06-20 16:38:30 -07006156 return status;
6157}
6158
6159/*
6160 * FUNCTION: wlan_hdd_cfg80211_join_ibss
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306161 * This function is used to create/join an IBSS
Jeff Johnson295189b2012-06-20 16:38:30 -07006162 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306163static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006164 struct net_device *dev,
6165 struct cfg80211_ibss_params *params
6166 )
6167{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306168 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07006169 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6170 tCsrRoamProfile *pRoamProfile;
6171 int status;
6172 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306173 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006174
6175 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306176
6177 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07006178 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
6179
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306180 status = wlan_hdd_validate_context(pHddCtx);
6181
6182 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07006183 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306184 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6185 "%s: HDD context is not valid", __func__);
6186 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006187 }
6188
6189 if (NULL == pWextState)
6190 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306191 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07006192 __func__);
6193 return -EIO;
6194 }
6195
6196 pRoamProfile = &pWextState->roamProfile;
6197
6198 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
6199 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306200 hddLog (VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006201 "%s Interface type is not set to IBSS \n", __func__);
6202 return -EINVAL;
6203 }
6204
6205 /* Set Channel */
Yue Maf49ba872013-08-19 12:04:25 -07006206 if (NULL !=
6207#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
6208 params->chandef.chan)
6209#else
6210 params->channel)
6211#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006212 {
6213 u8 channelNum;
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006214 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6215 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
6216 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
6217 int indx;
Jeff Johnson295189b2012-06-20 16:38:30 -07006218
6219 /* Get channel number */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306220 channelNum =
Yue Maf49ba872013-08-19 12:04:25 -07006221 ieee80211_frequency_to_channel(
6222#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
6223 params->chandef.chan->center_freq);
6224#else
6225 params->channel->center_freq);
6226#endif
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006227
6228 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
6229 validChan, &numChans))
Jeff Johnson295189b2012-06-20 16:38:30 -07006230 {
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006231 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
6232 __func__);
6233 return -EOPNOTSUPP;
Jeff Johnson295189b2012-06-20 16:38:30 -07006234 }
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006235
6236 for (indx = 0; indx < numChans; indx++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006237 {
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006238 if (channelNum == validChan[indx])
6239 {
6240 break;
6241 }
6242 }
6243 if (indx >= numChans)
6244 {
6245 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07006246 __func__, channelNum);
6247 return -EINVAL;
6248 }
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006249 /* Set the Operational Channel */
6250 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
6251 channelNum);
6252 pRoamProfile->ChannelInfo.numOfChannels = 1;
6253 pHddStaCtx->conn_info.operationChannel = channelNum;
6254 pRoamProfile->ChannelInfo.ChannelList =
6255 &pHddStaCtx->conn_info.operationChannel;
Jeff Johnson295189b2012-06-20 16:38:30 -07006256 }
6257
6258 /* Initialize security parameters */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306259 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
Jeff Johnson295189b2012-06-20 16:38:30 -07006260 if (status < 0)
6261 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306262 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
Jeff Johnson295189b2012-06-20 16:38:30 -07006263 __func__);
6264 return status;
6265 }
6266
6267 /* Issue connect start */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306268 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006269 params->ssid_len, params->bssid,
6270 pHddStaCtx->conn_info.operationChannel);
Jeff Johnson295189b2012-06-20 16:38:30 -07006271
6272 if (0 > status)
6273 {
6274 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
6275 return status;
6276 }
6277
6278 return 0;
6279}
6280
6281/*
6282 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306283 * This function is used to leave an IBSS
Jeff Johnson295189b2012-06-20 16:38:30 -07006284 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306285static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006286 struct net_device *dev
6287 )
6288{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306289 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07006290 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6291 tCsrRoamProfile *pRoamProfile;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306292 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6293 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006294
6295 ENTER();
6296
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306297 status = wlan_hdd_validate_context(pHddCtx);
6298
6299 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006300 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306301 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6302 "%s: HDD context is not valid", __func__);
6303 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006304 }
6305
Jeff Johnson295189b2012-06-20 16:38:30 -07006306 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
6307 if (NULL == pWextState)
6308 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306309 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07006310 __func__);
6311 return -EIO;
6312 }
6313
6314 pRoamProfile = &pWextState->roamProfile;
6315
6316 /* Issue disconnect only if interface type is set to IBSS */
6317 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
6318 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306319 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
Jeff Johnson295189b2012-06-20 16:38:30 -07006320 __func__);
6321 return -EINVAL;
6322 }
6323
6324 /* Issue Disconnect request */
6325 INIT_COMPLETION(pAdapter->disconnect_comp_var);
6326 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6327 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6328
6329 return 0;
6330}
6331
6332/*
6333 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
6334 * This function is used to set the phy parameters
6335 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
6336 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306337static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006338 u32 changed)
6339{
6340 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6341 tHalHandle hHal = pHddCtx->hHal;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306342 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006343
6344 ENTER();
6345
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306346 status = wlan_hdd_validate_context(pHddCtx);
6347
6348 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006349 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306350 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6351 "%s: HDD context is not valid", __func__);
6352 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006353 }
6354
Jeff Johnson295189b2012-06-20 16:38:30 -07006355 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
6356 {
6357 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
6358 WNI_CFG_RTS_THRESHOLD_STAMAX :
6359 wiphy->rts_threshold;
6360
6361 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306362 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
Jeff Johnson295189b2012-06-20 16:38:30 -07006363 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306364 hddLog(VOS_TRACE_LEVEL_ERROR,
6365 "%s: Invalid RTS Threshold value %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006366 __func__, rts_threshold);
6367 return -EINVAL;
6368 }
6369
6370 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
6371 rts_threshold, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306372 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07006373 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306374 hddLog(VOS_TRACE_LEVEL_ERROR,
6375 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006376 __func__, rts_threshold);
6377 return -EIO;
6378 }
6379
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306380 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07006381 rts_threshold);
6382 }
6383
6384 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
6385 {
6386 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
6387 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
6388 wiphy->frag_threshold;
6389
6390 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306391 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
Jeff Johnson295189b2012-06-20 16:38:30 -07006392 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306393 hddLog(VOS_TRACE_LEVEL_ERROR,
6394 "%s: Invalid frag_threshold value %hu", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07006395 frag_threshold);
6396 return -EINVAL;
6397 }
6398
6399 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
6400 frag_threshold, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306401 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07006402 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306403 hddLog(VOS_TRACE_LEVEL_ERROR,
6404 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006405 __func__, frag_threshold);
6406 return -EIO;
6407 }
6408
6409 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
6410 frag_threshold);
6411 }
6412
6413 if ((changed & WIPHY_PARAM_RETRY_SHORT)
6414 || (changed & WIPHY_PARAM_RETRY_LONG))
6415 {
6416 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
6417 wiphy->retry_short :
6418 wiphy->retry_long;
6419
6420 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
6421 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
6422 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306423 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006424 __func__, retry_value);
6425 return -EINVAL;
6426 }
6427
6428 if (changed & WIPHY_PARAM_RETRY_SHORT)
6429 {
6430 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
6431 retry_value, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306432 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07006433 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306434 hddLog(VOS_TRACE_LEVEL_ERROR,
6435 "%s: ccmCfgSetInt failed for long retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006436 __func__, retry_value);
6437 return -EIO;
6438 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306439 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006440 __func__, retry_value);
6441 }
6442 else if (changed & WIPHY_PARAM_RETRY_SHORT)
6443 {
6444 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
6445 retry_value, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306446 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07006447 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306448 hddLog(VOS_TRACE_LEVEL_ERROR,
6449 "%s: ccmCfgSetInt failed for short retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006450 __func__, retry_value);
6451 return -EIO;
6452 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306453 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006454 __func__, retry_value);
6455 }
6456 }
6457
6458 return 0;
6459}
6460
6461/*
6462 * FUNCTION: wlan_hdd_cfg80211_set_txpower
6463 * This function is used to set the txpower
6464 */
6465static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
Yue Maf49ba872013-08-19 12:04:25 -07006466#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
6467 struct wireless_dev *wdev,
6468#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006469#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306470 enum tx_power_setting type,
Jeff Johnson295189b2012-06-20 16:38:30 -07006471#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306472 enum nl80211_tx_power_setting type,
Jeff Johnson295189b2012-06-20 16:38:30 -07006473#endif
6474 int dbm)
6475{
6476 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306477 tHalHandle hHal = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006478 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
6479 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306480 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006481
6482 ENTER();
6483
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306484 status = wlan_hdd_validate_context(pHddCtx);
6485
6486 if (0 != status)
6487 {
6488 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6489 "%s: HDD context is not valid", __func__);
6490 return status;
6491 }
6492
6493 hHal = pHddCtx->hHal;
6494
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306495 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
6496 dbm, ccmCfgSetCallback,
6497 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07006498 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306499 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006500 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
6501 return -EIO;
6502 }
6503
6504 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
6505 dbm);
6506
6507 switch(type)
6508 {
6509 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
6510 /* Fall through */
6511 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
6512 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
6513 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306514 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
6515 __func__);
6516 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006517 }
6518 break;
6519 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306520 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
Jeff Johnson295189b2012-06-20 16:38:30 -07006521 __func__);
6522 return -EOPNOTSUPP;
6523 break;
6524 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306525 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
6526 __func__, type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006527 return -EIO;
6528 }
6529
6530 return 0;
6531}
6532
6533/*
6534 * FUNCTION: wlan_hdd_cfg80211_get_txpower
6535 * This function is used to read the txpower
6536 */
Yue Maf49ba872013-08-19 12:04:25 -07006537static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy,
6538#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
6539 struct wireless_dev *wdev,
6540#endif
6541 int *dbm)
Jeff Johnson295189b2012-06-20 16:38:30 -07006542{
6543
6544 hdd_adapter_t *pAdapter;
6545 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306546 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006547
Jeff Johnsone7245742012-09-05 17:12:55 -07006548 ENTER();
6549
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306550 status = wlan_hdd_validate_context(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006551
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306552 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006553 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306554 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6555 "%s: HDD context is not valid", __func__);
6556 *dbm = 0;
6557 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006558 }
6559
Jeff Johnson295189b2012-06-20 16:38:30 -07006560 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
6561 if (NULL == pAdapter)
6562 {
6563 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
6564 return -ENOENT;
6565 }
6566
6567 wlan_hdd_get_classAstats(pAdapter);
6568 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
6569
Jeff Johnsone7245742012-09-05 17:12:55 -07006570 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006571 return 0;
6572}
6573
6574static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
6575 u8* mac, struct station_info *sinfo)
6576{
6577 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
6578 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6579 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
6580 tANI_U8 rate_flags;
6581
6582 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6583 hdd_config_t *pCfg = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07006584
6585 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
6586 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
6587 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
6588 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
6589 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
6590 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
6591 tANI_U16 maxRate = 0;
6592 tANI_U16 myRate;
6593 tANI_U16 currentRate = 0;
6594 tANI_U8 maxSpeedMCS = 0;
6595 tANI_U8 maxMCSIdx = 0;
6596 tANI_U8 rateFlag = 1;
6597 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006598 tANI_U16 temp;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306599 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006600
Leo Chang6f8870f2013-03-26 18:11:36 -07006601#ifdef WLAN_FEATURE_11AC
6602 tANI_U32 vht_mcs_map;
6603 eDataRate11ACMaxMcs vhtMaxMcs;
6604#endif /* WLAN_FEATURE_11AC */
6605
Jeff Johnsone7245742012-09-05 17:12:55 -07006606 ENTER();
6607
Jeff Johnson295189b2012-06-20 16:38:30 -07006608 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
6609 (0 == ssidlen))
6610 {
6611 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
6612 " Invalid ssidlen, %d", __func__, ssidlen);
6613 /*To keep GUI happy*/
6614 return 0;
6615 }
6616
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306617 status = wlan_hdd_validate_context(pHddCtx);
6618
6619 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006620 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306621 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6622 "%s: HDD context is not valid", __func__);
6623 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006624 }
6625
Jeff Johnson295189b2012-06-20 16:38:30 -07006626 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
6627 sinfo->filled |= STATION_INFO_SIGNAL;
6628
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006629 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006630 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
6631
6632 //convert to the UI units of 100kbps
6633 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
6634
6635#ifdef LINKSPEED_DEBUG_ENABLED
Leo Chang6f8870f2013-03-26 18:11:36 -07006636 pr_info("RSSI %d, RLMS %u, rate %d, rssi high %d, rssi mid %d, rssi low %d, rate_flags 0x%x, MCS %d\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07006637 sinfo->signal,
6638 pCfg->reportMaxLinkSpeed,
6639 myRate,
6640 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006641 (int) pCfg->linkSpeedRssiMid,
6642 (int) pCfg->linkSpeedRssiLow,
Leo Chang6f8870f2013-03-26 18:11:36 -07006643 (int) rate_flags,
6644 (int) pAdapter->hdd_stats.ClassA_stat.mcs_index);
Jeff Johnson295189b2012-06-20 16:38:30 -07006645#endif //LINKSPEED_DEBUG_ENABLED
6646
6647 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
6648 {
6649 // we do not want to necessarily report the current speed
6650 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
6651 {
6652 // report the max possible speed
6653 rssidx = 0;
6654 }
6655 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
6656 {
6657 // report the max possible speed with RSSI scaling
6658 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
6659 {
6660 // report the max possible speed
6661 rssidx = 0;
6662 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006663 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07006664 {
6665 // report middle speed
6666 rssidx = 1;
6667 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006668 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
6669 {
6670 // report middle speed
6671 rssidx = 2;
6672 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006673 else
6674 {
6675 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006676 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07006677 }
6678 }
6679 else
6680 {
6681 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
6682 hddLog(VOS_TRACE_LEVEL_ERROR,
6683 "%s: Invalid value for reportMaxLinkSpeed: %u",
6684 __func__, pCfg->reportMaxLinkSpeed);
6685 rssidx = 0;
6686 }
6687
6688 maxRate = 0;
6689
6690 /* Get Basic Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306691 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_OPERATIONAL_RATE_SET,
6692 OperationalRates, &ORLeng))
6693 {
6694 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6695 /*To keep GUI happy*/
6696 return 0;
6697 }
6698
Jeff Johnson295189b2012-06-20 16:38:30 -07006699 for (i = 0; i < ORLeng; i++)
6700 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006701 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006702 {
6703 /* Validate Rate Set */
6704 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
6705 {
6706 currentRate = supported_data_rate[j].supported_rate[rssidx];
6707 break;
6708 }
6709 }
6710 /* Update MAX rate */
6711 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6712 }
6713
6714 /* Get Extended Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306715 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
6716 ExtendedRates, &ERLeng))
6717 {
6718 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6719 /*To keep GUI happy*/
6720 return 0;
6721 }
6722
Jeff Johnson295189b2012-06-20 16:38:30 -07006723 for (i = 0; i < ERLeng; i++)
6724 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006725 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006726 {
6727 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
6728 {
6729 currentRate = supported_data_rate[j].supported_rate[rssidx];
6730 break;
6731 }
6732 }
6733 /* Update MAX rate */
6734 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6735 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006736 /* Get MCS Rate Set -- but only if we are connected at MCS
6737 rates or if we are always reporting max speed or if we have
6738 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006739 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07006740 {
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306741 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_CURRENT_MCS_SET,
6742 MCSRates, &MCSLeng))
6743 {
6744 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6745 /*To keep GUI happy*/
6746 return 0;
6747 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006748 rateFlag = 0;
Leo Chang6f8870f2013-03-26 18:11:36 -07006749#ifdef WLAN_FEATURE_11AC
6750 /* VHT80 rate has seperate rate table */
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306751 if (rate_flags & (eHAL_TX_RATE_VHT20|eHAL_TX_RATE_VHT40|eHAL_TX_RATE_VHT80))
Jeff Johnson295189b2012-06-20 16:38:30 -07006752 {
Leo Chang6f8870f2013-03-26 18:11:36 -07006753 ccmCfgGetInt(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_VHT_TX_MCS_MAP, &vht_mcs_map);
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306754 vhtMaxMcs = (eDataRate11ACMaxMcs)(vht_mcs_map & DATA_RATE_11AC_MCS_MASK );
Leo Chang6f8870f2013-03-26 18:11:36 -07006755 if (rate_flags & eHAL_TX_RATE_SGI)
Jeff Johnson295189b2012-06-20 16:38:30 -07006756 {
Leo Chang6f8870f2013-03-26 18:11:36 -07006757 rateFlag |= 1;
Jeff Johnson295189b2012-06-20 16:38:30 -07006758 }
Leo Chang6f8870f2013-03-26 18:11:36 -07006759 if (DATA_RATE_11AC_MAX_MCS_7 == vhtMaxMcs)
Jeff Johnson295189b2012-06-20 16:38:30 -07006760 {
Leo Chang6f8870f2013-03-26 18:11:36 -07006761 maxMCSIdx = 7;
6762 }
6763 else if (DATA_RATE_11AC_MAX_MCS_8 == vhtMaxMcs)
6764 {
6765 maxMCSIdx = 8;
6766 }
6767 else if (DATA_RATE_11AC_MAX_MCS_9 == vhtMaxMcs)
6768 {
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306769 //VHT20 is supporting 0~8
6770 if (rate_flags & eHAL_TX_RATE_VHT20)
6771 maxMCSIdx = 8;
6772 else
6773 maxMCSIdx = 9;
Leo Chang6f8870f2013-03-26 18:11:36 -07006774 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306775
6776 if (rate_flags & eHAL_TX_RATE_VHT80)
6777 {
6778 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT80_rate[rateFlag];
6779 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT80_rate[rateFlag];
6780 }
6781 else if (rate_flags & eHAL_TX_RATE_VHT40)
6782 {
6783 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT40_rate[rateFlag];
6784 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT40_rate[rateFlag];
6785 }
6786 else if (rate_flags & eHAL_TX_RATE_VHT20)
6787 {
6788 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT20_rate[rateFlag];
6789 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT20_rate[rateFlag];
6790 }
6791
Leo Chang6f8870f2013-03-26 18:11:36 -07006792 maxSpeedMCS = 1;
6793 if (currentRate > maxRate)
6794 {
6795 maxRate = currentRate;
6796 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306797
Leo Chang6f8870f2013-03-26 18:11:36 -07006798 }
6799 else
6800#endif /* WLAN_FEATURE_11AC */
6801 {
6802 if (rate_flags & eHAL_TX_RATE_HT40)
6803 {
6804 rateFlag |= 1;
6805 }
6806 if (rate_flags & eHAL_TX_RATE_SGI)
6807 {
6808 rateFlag |= 2;
6809 }
6810
6811 for (i = 0; i < MCSLeng; i++)
6812 {
6813 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
6814 for (j = 0; j < temp; j++)
6815 {
6816 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
6817 {
6818 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
6819 break;
6820 }
6821 }
6822 if ((j < temp) && (currentRate > maxRate))
6823 {
6824 maxRate = currentRate;
6825 maxSpeedMCS = 1;
6826 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
6827 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006828 }
6829 }
6830 }
6831
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306832 else if (!(rate_flags & eHAL_TX_RATE_LEGACY))
6833 {
6834 maxRate = myRate;
6835 maxSpeedMCS = 1;
6836 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6837 }
6838
Jeff Johnson295189b2012-06-20 16:38:30 -07006839 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006840 if (((maxRate < myRate) && (0 == rssidx)) ||
6841 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006842 {
6843 maxRate = myRate;
6844 if (rate_flags & eHAL_TX_RATE_LEGACY)
6845 {
6846 maxSpeedMCS = 0;
6847 }
6848 else
6849 {
6850 maxSpeedMCS = 1;
6851 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6852 }
6853 }
6854
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306855 if (rate_flags & eHAL_TX_RATE_LEGACY)
Jeff Johnson295189b2012-06-20 16:38:30 -07006856 {
6857 sinfo->txrate.legacy = maxRate;
6858#ifdef LINKSPEED_DEBUG_ENABLED
6859 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
6860#endif //LINKSPEED_DEBUG_ENABLED
6861 }
6862 else
6863 {
6864 sinfo->txrate.mcs = maxMCSIdx;
Leo Chang6f8870f2013-03-26 18:11:36 -07006865#ifdef WLAN_FEATURE_11AC
6866 sinfo->txrate.nss = 1;
6867 if (rate_flags & eHAL_TX_RATE_VHT80)
6868 {
6869 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306870 sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Leo Chang6f8870f2013-03-26 18:11:36 -07006871 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306872 else if (rate_flags & eHAL_TX_RATE_VHT40)
Leo Chang6f8870f2013-03-26 18:11:36 -07006873 {
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306874 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
6875 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6876 }
6877 else if (rate_flags & eHAL_TX_RATE_VHT20)
6878 {
6879 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
6880 }
6881#endif /* WLAN_FEATURE_11AC */
6882 if (rate_flags & (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40))
6883 {
6884 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6885 if (rate_flags & eHAL_TX_RATE_HT40)
6886 {
6887 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6888 }
Leo Chang6f8870f2013-03-26 18:11:36 -07006889 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006890 if (rate_flags & eHAL_TX_RATE_SGI)
6891 {
6892 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6893 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306894
Jeff Johnson295189b2012-06-20 16:38:30 -07006895#ifdef LINKSPEED_DEBUG_ENABLED
6896 pr_info("Reporting MCS rate %d flags %x\n",
6897 sinfo->txrate.mcs,
6898 sinfo->txrate.flags );
6899#endif //LINKSPEED_DEBUG_ENABLED
6900 }
6901 }
6902 else
6903 {
6904 // report current rate instead of max rate
6905
6906 if (rate_flags & eHAL_TX_RATE_LEGACY)
6907 {
6908 //provide to the UI in units of 100kbps
6909 sinfo->txrate.legacy = myRate;
6910#ifdef LINKSPEED_DEBUG_ENABLED
6911 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
6912#endif //LINKSPEED_DEBUG_ENABLED
6913 }
6914 else
6915 {
6916 //must be MCS
6917 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
Leo Chang6f8870f2013-03-26 18:11:36 -07006918#ifdef WLAN_FEATURE_11AC
6919 sinfo->txrate.nss = 1;
6920 if (rate_flags & eHAL_TX_RATE_VHT80)
6921 {
6922 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
6923 }
6924 else
6925#endif /* WLAN_FEATURE_11AC */
6926 {
6927 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6928 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006929 if (rate_flags & eHAL_TX_RATE_SGI)
6930 {
6931 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6932 }
6933 if (rate_flags & eHAL_TX_RATE_HT40)
6934 {
6935 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6936 }
Leo Chang6f8870f2013-03-26 18:11:36 -07006937#ifdef WLAN_FEATURE_11AC
6938 else if (rate_flags & eHAL_TX_RATE_VHT80)
6939 {
6940 sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
6941 }
6942#endif /* WLAN_FEATURE_11AC */
Jeff Johnson295189b2012-06-20 16:38:30 -07006943#ifdef LINKSPEED_DEBUG_ENABLED
6944 pr_info("Reporting actual MCS rate %d flags %x\n",
6945 sinfo->txrate.mcs,
6946 sinfo->txrate.flags );
6947#endif //LINKSPEED_DEBUG_ENABLED
6948 }
6949 }
6950 sinfo->filled |= STATION_INFO_TX_BITRATE;
6951
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006952 sinfo->tx_packets =
6953 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
6954 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
6955 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
6956 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
6957
6958 sinfo->tx_retries =
6959 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
6960 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
6961 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
6962 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
6963
6964 sinfo->tx_failed =
6965 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
6966 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
6967 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
6968 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
6969
6970 sinfo->filled |=
6971 STATION_INFO_TX_PACKETS |
6972 STATION_INFO_TX_RETRIES |
6973 STATION_INFO_TX_FAILED;
6974
6975 EXIT();
6976 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006977}
6978
6979static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
Sameer Thalappilc9f26e92013-06-07 10:11:06 -07006980 struct net_device *dev, bool mode, int timeout)
Jeff Johnson295189b2012-06-20 16:38:30 -07006981{
6982 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05306983 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07006984 VOS_STATUS vos_status;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306985 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006986
Jeff Johnsone7245742012-09-05 17:12:55 -07006987 ENTER();
6988
Jeff Johnson295189b2012-06-20 16:38:30 -07006989 if (NULL == pAdapter)
6990 {
6991 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6992 return -ENODEV;
6993 }
6994
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05306995 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306996 status = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05306997
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306998 if (0 != status)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306999 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307000 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7001 "%s: HDD context is not valid", __func__);
7002 return status;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307003 }
7004
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05307005 if ((DRIVER_POWER_MODE_AUTO == !mode) &&
7006 (TRUE == pHddCtx->hdd_wlan_suspended) &&
7007 (pHddCtx->cfg_ini->fhostArpOffload) &&
7008 (eConnectionState_Associated ==
7009 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
7010 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05307011 vos_status = hdd_conf_arp_offload(pAdapter, TRUE);
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05307012 if (!VOS_IS_STATUS_SUCCESS(vos_status))
7013 {
7014 hddLog(VOS_TRACE_LEVEL_INFO,
7015 "%s:Failed to enable ARPOFFLOAD Feature %d\n",
7016 __func__, vos_status);
7017 }
7018 }
7019
Jeff Johnson295189b2012-06-20 16:38:30 -07007020 /**The get power cmd from the supplicant gets updated by the nl only
7021 *on successful execution of the function call
7022 *we are oppositely mapped w.r.t mode in the driver
7023 **/
7024 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
7025
Jeff Johnsone7245742012-09-05 17:12:55 -07007026 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07007027 if (VOS_STATUS_E_FAILURE == vos_status)
7028 {
7029 return -EINVAL;
7030 }
7031 return 0;
7032}
7033
7034
7035#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7036static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
7037 struct net_device *netdev,
7038 u8 key_index)
7039{
Jeff Johnsone7245742012-09-05 17:12:55 -07007040 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007041 return 0;
7042}
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307043#endif //LINUX_VERSION_CODE
Jeff Johnson295189b2012-06-20 16:38:30 -07007044
7045#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
7046static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
7047 struct net_device *dev,
7048 struct ieee80211_txq_params *params)
7049{
Jeff Johnsone7245742012-09-05 17:12:55 -07007050 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007051 return 0;
7052}
7053#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7054static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
7055 struct ieee80211_txq_params *params)
7056{
Jeff Johnsone7245742012-09-05 17:12:55 -07007057 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007058 return 0;
7059}
7060#endif //LINUX_VERSION_CODE
7061
7062static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
7063 struct net_device *dev, u8 *mac)
7064{
7065 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307066 hdd_context_t *pHddCtx;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007067 VOS_STATUS vos_status;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307068 int status;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007069 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07007070
Jeff Johnsone7245742012-09-05 17:12:55 -07007071 ENTER();
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307072 if ( NULL == pAdapter )
Jeff Johnson295189b2012-06-20 16:38:30 -07007073 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307074 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007075 return -EINVAL;
7076 }
7077
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307078 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7079 status = wlan_hdd_validate_context(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007080
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307081 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007082 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307083 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7084 "%s: HDD context is not valid", __func__);
7085 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007086 }
7087
Jeff Johnson295189b2012-06-20 16:38:30 -07007088 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07007089 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07007090 )
7091 {
7092 if( NULL == mac )
7093 {
7094 v_U16_t i;
7095 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
7096 {
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07007097 if ((pAdapter->aStaInfo[i].isUsed) &&
7098 (!pAdapter->aStaInfo[i].isDeauthInProgress))
Jeff Johnson295189b2012-06-20 16:38:30 -07007099 {
7100 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
7101 hddLog(VOS_TRACE_LEVEL_INFO,
7102 "%s: Delete STA with MAC::"
7103 "%02x:%02x:%02x:%02x:%02x:%02x",
7104 __func__,
7105 macAddr[0], macAddr[1], macAddr[2],
7106 macAddr[3], macAddr[4], macAddr[5]);
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07007107 vos_status = hdd_softap_sta_deauth(pAdapter, macAddr);
7108 if (VOS_IS_STATUS_SUCCESS(vos_status))
7109 pAdapter->aStaInfo[i].isDeauthInProgress = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007110 }
7111 }
7112 }
7113 else
7114 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007115
7116 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
7117 if (!VOS_IS_STATUS_SUCCESS(vos_status))
7118 {
7119 hddLog(VOS_TRACE_LEVEL_INFO,
7120 "%s: Skip this DEL STA as this is not used::"
7121 "%02x:%02x:%02x:%02x:%02x:%02x",
7122 __func__,
7123 mac[0], mac[1], mac[2],
7124 mac[3], mac[4], mac[5]);
7125 return -ENOENT;
7126 }
7127
7128 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
7129 {
7130 hddLog(VOS_TRACE_LEVEL_INFO,
7131 "%s: Skip this DEL STA as deauth is in progress::"
7132 "%02x:%02x:%02x:%02x:%02x:%02x",
7133 __func__,
7134 mac[0], mac[1], mac[2],
7135 mac[3], mac[4], mac[5]);
7136 return -ENOENT;
7137 }
7138
7139 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
7140
Jeff Johnson295189b2012-06-20 16:38:30 -07007141 hddLog(VOS_TRACE_LEVEL_INFO,
7142 "%s: Delete STA with MAC::"
7143 "%02x:%02x:%02x:%02x:%02x:%02x",
7144 __func__,
7145 mac[0], mac[1], mac[2],
7146 mac[3], mac[4], mac[5]);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007147
7148 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
7149 if (!VOS_IS_STATUS_SUCCESS(vos_status))
7150 {
7151 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
7152 hddLog(VOS_TRACE_LEVEL_INFO,
7153 "%s: STA removal failed for ::"
7154 "%02x:%02x:%02x:%02x:%02x:%02x",
7155 __func__,
7156 mac[0], mac[1], mac[2],
7157 mac[3], mac[4], mac[5]);
7158 return -ENOENT;
7159 }
7160
Jeff Johnson295189b2012-06-20 16:38:30 -07007161 }
7162 }
7163
7164 EXIT();
7165
7166 return 0;
7167}
7168
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007169static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
7170 struct net_device *dev, u8 *mac, struct station_parameters *params)
7171{
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007172 int status = -EPERM;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007173#ifdef FEATURE_WLAN_TDLS
7174 u32 mask, set;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007175 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007176 mask = params->sta_flags_mask;
7177
7178 set = params->sta_flags_set;
7179
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007180#ifdef WLAN_FEATURE_TDLS_DEBUG
7181 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7182 "%s: mask 0x%x set 0x%x " MAC_ADDRESS_STR,
7183 __func__, mask, set, MAC_ADDR_ARRAY(mac));
7184#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007185
7186 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
7187 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08007188 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007189 }
7190 }
7191#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007192 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07007193}
7194
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007195
7196#ifdef FEATURE_WLAN_LFR
7197static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07007198 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007199{
7200#define MAX_PMKSAIDS_IN_CACHE 8
7201 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307202 static tANI_U32 i; // HDD Local Cache index
7203 tANI_U32 j=0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007204 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7205 tHalHandle halHandle;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307206 eHalStatus result;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307207 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007208 tANI_U8 BSSIDMatched = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307209 hdd_context_t *pHddCtx;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307210
Jeff Johnsone7245742012-09-05 17:12:55 -07007211 ENTER();
7212
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307213 // Validate pAdapter
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307214 if ( NULL == pAdapter )
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007215 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307216 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007217 return -EINVAL;
7218 }
7219
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307220 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7221 status = wlan_hdd_validate_context(pHddCtx);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007222
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307223 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007224 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307225 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7226 "%s: HDD context is not valid", __func__);
7227 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007228 }
7229
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307230 // Retrieve halHandle
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007231 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
7232
7233 for (j = 0; j < i; j++)
7234 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307235 if(vos_mem_compare(PMKIDCache[j].BSSID,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007236 pmksa->bssid, WNI_CFG_BSSID_LEN))
7237 {
7238 /* BSSID matched previous entry. Overwrite it. */
7239 BSSIDMatched = 1;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307240 vos_mem_copy(PMKIDCache[j].BSSID,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007241 pmksa->bssid, WNI_CFG_BSSID_LEN);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307242 vos_mem_copy(PMKIDCache[j].PMKID,
7243 pmksa->pmkid,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007244 CSR_RSN_PMKID_SIZE);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307245 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007246 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007247 dump_bssid(pmksa->bssid);
7248 dump_pmkid(halHandle, pmksa->pmkid);
7249 break;
7250 }
7251 }
7252
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07007253 /* Check we compared all entries,if then take the first slot now */
7254 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
7255
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007256 if (!BSSIDMatched)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307257 {
7258 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
7259 vos_mem_copy(PMKIDCache[i].BSSID,
7260 pmksa->bssid, ETHER_ADDR_LEN);
7261 vos_mem_copy(PMKIDCache[i].PMKID,
7262 pmksa->pmkid,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007263 CSR_RSN_PMKID_SIZE);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307264 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007265 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007266 dump_bssid(pmksa->bssid);
7267 dump_pmkid(halHandle, pmksa->pmkid);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307268 // Increment the HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007269 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307270 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007271 }
7272
7273
7274 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307275 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007276 // __func__, i );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307277 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007278 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007279 // Finally set the PMKSA ID Cache in CSR
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307280 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
7281 PMKIDCache,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007282 i );
7283 return 0;
7284}
7285
7286
7287static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07007288 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007289{
Jeff Johnsone7245742012-09-05 17:12:55 -07007290 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007291 // TODO: Implement this later.
7292 return 0;
7293}
7294
7295static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
7296{
Jeff Johnsone7245742012-09-05 17:12:55 -07007297 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007298 // TODO: Implement this later.
7299 return 0;
7300}
7301#endif
7302
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007303#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307304static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007305 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
7306{
7307 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7308 hdd_station_ctx_t *pHddStaCtx;
7309
7310 if (NULL == pAdapter)
7311 {
7312 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
7313 return -ENODEV;
7314 }
7315
7316 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7317
7318 // Added for debug on reception of Re-assoc Req.
7319 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
7320 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307321 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007322 ftie->ie_len);
7323 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
7324 }
7325
7326#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307327 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007328 ftie->ie_len);
7329#endif
7330
7331 // Pass the received FT IEs to SME
Gopichand Nakkala356fb102013-03-06 12:34:04 +05307332 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
7333 (const u8 *)ftie->ie,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007334 ftie->ie_len);
7335 return 0;
7336}
7337#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007338
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307339#ifdef FEATURE_WLAN_SCAN_PNO
7340
7341void hdd_cfg80211_sched_scan_done_callback(void *callbackContext,
7342 tSirPrefNetworkFoundInd *pPrefNetworkFoundInd)
7343{
7344 int ret;
7345 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
7346 hdd_context_t *pHddCtx;
7347
7348 if (NULL == pAdapter)
7349 {
7350 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7351 "%s: HDD adapter is Null", __func__);
7352 return ;
7353 }
7354
7355 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7356 if (NULL == pHddCtx)
7357 {
7358 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7359 "%s: HDD context is Null!!!", __func__);
7360 return ;
7361 }
7362
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307363 spin_lock(&pHddCtx->schedScan_lock);
7364 if (TRUE == pHddCtx->isWiphySuspended)
7365 {
7366 pHddCtx->isSchedScanUpdatePending = TRUE;
7367 spin_unlock(&pHddCtx->schedScan_lock);
7368 hddLog(VOS_TRACE_LEVEL_INFO,
7369 "%s: Update cfg80211 scan database after it resume", __func__);
7370 return ;
7371 }
7372 spin_unlock(&pHddCtx->schedScan_lock);
7373
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307374 ret = wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter);
7375
7376 if (0 > ret)
7377 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
7378
7379 cfg80211_sched_scan_results(pHddCtx->wiphy);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307380 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7381 "%s: cfg80211 scan result database updated", __func__);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307382}
7383
7384/*
7385 * FUNCTION: wlan_hdd_cfg80211_sched_scan_start
7386 * NL interface to enable PNO
7387 */
7388static int wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy,
7389 struct net_device *dev, struct cfg80211_sched_scan_request *request)
7390{
7391 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7392 tpSirPNOScanReq pPnoRequest = NULL;
7393 hdd_context_t *pHddCtx;
7394 tHalHandle hHal;
Madan Mohan Koyyalamudi1d16f462013-08-27 16:25:34 +05307395 v_U32_t i, indx, num_ch, tempInterval;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307396 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
7397 u8 channels_allowed[WNI_CFG_VALID_CHANNEL_LIST_LEN];
7398 v_U32_t num_channels_allowed = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7399 eHalStatus status = eHAL_STATUS_FAILURE;
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307400 int ret = 0;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307401
7402 if (NULL == pAdapter)
7403 {
7404 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7405 "%s: HDD adapter is Null", __func__);
7406 return -ENODEV;
7407 }
7408
7409 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307410 ret = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307411
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307412 if (0 != ret)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307413 {
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05307414 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7415 "%s: HDD context is not valid", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307416 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307417 }
7418
7419 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
7420 if (NULL == hHal)
7421 {
7422 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7423 "%s: HAL context is Null!!!", __func__);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307424 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307425 }
7426
7427 pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq));
7428 if (NULL == pPnoRequest)
7429 {
7430 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7431 "%s: vos_mem_malloc failed", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307432 return -ENOMEM;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307433 }
7434
Madan Mohan Koyyalamudic3f04352013-09-26 19:21:48 +05307435 memset(pPnoRequest, 0, sizeof (tSirPNOScanReq));
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307436 pPnoRequest->enable = 1; /*Enable PNO */
7437 pPnoRequest->ucNetworksCount = request->n_match_sets;
7438
7439 if (( !pPnoRequest->ucNetworksCount ) ||
7440 ( pPnoRequest->ucNetworksCount > SIR_PNO_MAX_SUPP_NETWORKS ))
7441 {
7442 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7443 "Network input is not correct");
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307444 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307445 goto error;
7446 }
7447
7448 if ( SIR_PNO_MAX_NETW_CHANNELS_EX < request->n_channels )
7449 {
7450 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7451 "Incorrect number of channels");
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307452 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307453 goto error;
7454 }
7455
7456 /* Framework provides one set of channels(all)
7457 * common for all saved profile */
7458 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
7459 channels_allowed, &num_channels_allowed))
7460 {
7461 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7462 "%s: failed to get valid channel list", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307463 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307464 goto error;
7465 }
7466 /* Checking each channel against allowed channel list */
7467 num_ch = 0;
7468 for (i = 0; i < request->n_channels; i++)
7469 {
7470 for (indx = 0; indx < num_channels_allowed; indx++)
7471 {
7472 if (request->channels[i]->hw_value == channels_allowed[indx])
7473 {
7474 valid_ch[num_ch++] = request->channels[i]->hw_value;
7475 break ;
7476 }
7477 }
7478 }
7479
7480 /* Filling per profile params */
7481 for (i = 0; i < pPnoRequest->ucNetworksCount; i++)
7482 {
7483 pPnoRequest->aNetworks[i].ssId.length =
7484 request->match_sets[i].ssid.ssid_len;
7485
7486 if (( 0 == pPnoRequest->aNetworks[i].ssId.length ) ||
7487 ( pPnoRequest->aNetworks[i].ssId.length > 32 ) )
7488 {
7489 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7490 "SSID Len %d is not correct for network %d",
7491 pPnoRequest->aNetworks[i].ssId.length, i);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307492 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307493 goto error;
7494 }
7495
7496 memcpy(pPnoRequest->aNetworks[i].ssId.ssId,
7497 request->match_sets[i].ssid.ssid,
7498 request->match_sets[i].ssid.ssid_len);
7499 pPnoRequest->aNetworks[i].authentication = 0; /*eAUTH_TYPE_ANY*/
7500 pPnoRequest->aNetworks[i].encryption = 0; /*eED_ANY*/
7501 pPnoRequest->aNetworks[i].bcastNetwType = 0; /*eBCAST_UNKNOWN*/
7502
7503 /*Copying list of valid channel into request */
7504 memcpy(pPnoRequest->aNetworks[i].aChannels, valid_ch, num_ch);
7505 pPnoRequest->aNetworks[i].ucChannelCount = num_ch;
7506
7507 pPnoRequest->aNetworks[i].rssiThreshold = 0; //Default value
7508 }
7509
Madan Mohan Koyyalamudia7765d52013-09-18 16:49:56 +05307510 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7511 "request->ie_len = %d", request->ie_len);
7512 if ((0 < request->ie_len) && (NULL != request->ie))
7513 {
7514 pPnoRequest->us24GProbeTemplateLen = request->ie_len;
7515 memcpy(&pPnoRequest->p24GProbeTemplate, request->ie,
7516 pPnoRequest->us24GProbeTemplateLen);
7517
7518 pPnoRequest->us5GProbeTemplateLen = request->ie_len;
7519 memcpy(&pPnoRequest->p5GProbeTemplate, request->ie,
7520 pPnoRequest->us5GProbeTemplateLen);
7521 }
7522
Madan Mohan Koyyalamudi1d16f462013-08-27 16:25:34 +05307523 /* Driver gets only one time interval which is hardcoded in
7524 * supplicant for 10000ms. Taking power consumption into account 6 timers
7525 * will be used, Timervalue is increased exponentially i.e 10,20,40,
7526 * 80,160,320 secs. And number of scan cycle for each timer
7527 * is configurable through INI param gPNOScanTimerRepeatValue.
7528 * If it is set to 0 only one timer will be used and PNO scan cycle
7529 * will be repeated after each interval specified by supplicant
7530 * till PNO is disabled.
7531 */
7532 if (0 == pHddCtx->cfg_ini->configPNOScanTimerRepeatValue)
7533 pPnoRequest->scanTimers.ucScanTimersCount = HDD_PNO_SCAN_TIMERS_SET_ONE;
7534 else
7535 pPnoRequest->scanTimers.ucScanTimersCount =
7536 HDD_PNO_SCAN_TIMERS_SET_MULTIPLE;
7537
7538 tempInterval = (request->interval)/1000;
7539 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7540 "Base scan interval = %d PNOScanTimerRepeatValue = %d",
7541 tempInterval, pHddCtx->cfg_ini->configPNOScanTimerRepeatValue);
7542 for ( i = 0; i < pPnoRequest->scanTimers.ucScanTimersCount; i++)
7543 {
7544 pPnoRequest->scanTimers.aTimerValues[i].uTimerRepeat =
7545 pHddCtx->cfg_ini->configPNOScanTimerRepeatValue;
7546 pPnoRequest->scanTimers.aTimerValues[i].uTimerValue = tempInterval;
7547 tempInterval *= 2;
7548 }
7549 //Repeat last timer until pno disabled.
7550 pPnoRequest->scanTimers.aTimerValues[i-1].uTimerRepeat = 0;
7551
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307552 pPnoRequest->modePNO = SIR_PNO_MODE_ON_SUSPEND;
7553
7554 status = sme_SetPreferredNetworkList(WLAN_HDD_GET_HAL_CTX(pAdapter),
7555 pPnoRequest, pAdapter->sessionId,
7556 hdd_cfg80211_sched_scan_done_callback, pAdapter);
7557 if (eHAL_STATUS_SUCCESS != status)
7558 {
7559 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7560 "Failed to enable PNO");
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307561 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307562 goto error;
7563 }
7564
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307565 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7566 "PNO scanRequest offloaded");
7567
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307568error:
7569 vos_mem_free(pPnoRequest);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307570 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307571}
7572
7573/*
7574 * FUNCTION: wlan_hdd_cfg80211_sched_scan_stop
7575 * NL interface to disable PNO
7576 */
7577static int wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy,
7578 struct net_device *dev)
7579{
7580 eHalStatus status = eHAL_STATUS_FAILURE;
7581 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7582 hdd_context_t *pHddCtx;
7583 tHalHandle hHal;
7584 tpSirPNOScanReq pPnoRequest = NULL;
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307585 int ret = 0;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307586
7587 ENTER();
7588
7589 if (NULL == pAdapter)
7590 {
7591 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7592 "%s: HDD adapter is Null", __func__);
7593 return -ENODEV;
7594 }
7595
7596 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307597
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307598 if (NULL == pHddCtx)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307599 {
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05307600 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307601 "%s: HDD context is Null", __func__);
7602 return -ENODEV;
7603 }
7604
7605 /* The return 0 is intentional when isLogpInProgress and
7606 * isLoadUnloadInProgress. We did observe a crash due to a return of
7607 * failure in sched_scan_stop , especially for a case where the unload
7608 * of the happens at the same time. The function __cfg80211_stop_sched_scan
7609 * was clearing rdev->sched_scan_req only when the sched_scan_stop returns
7610 * success. If it returns a failure , then its next invocation due to the
7611 * clean up of the second interface will have the dev pointer corresponding
7612 * to the first one leading to a crash.
7613 */
7614 if (pHddCtx->isLogpInProgress)
7615 {
7616 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7617 "%s: LOGP in Progress. Ignore!!!", __func__);
7618 return ret;
7619 }
7620
7621 if (pHddCtx->isLoadUnloadInProgress)
7622 {
7623 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7624 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
7625 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307626 }
7627
7628 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
7629 if (NULL == hHal)
7630 {
7631 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7632 "%s: HAL context is Null!!!", __func__);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307633 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307634 }
7635
7636 pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq));
7637 if (NULL == pPnoRequest)
7638 {
7639 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7640 "%s: vos_mem_malloc failed", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307641 return -ENOMEM;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307642 }
7643
7644 memset(pPnoRequest, 0, sizeof (tSirPNOScanReq));
7645 pPnoRequest->enable = 0; /* Disable PNO */
7646 pPnoRequest->ucNetworksCount = 0;
7647
7648 status = sme_SetPreferredNetworkList(hHal, pPnoRequest,
7649 pAdapter->sessionId,
7650 NULL, pAdapter);
7651 if (eHAL_STATUS_SUCCESS != status)
7652 {
7653 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7654 "Failed to disabled PNO");
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307655 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307656 }
7657
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307658 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7659 "%s: PNO scan disabled", __func__);
7660
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307661 vos_mem_free(pPnoRequest);
7662
7663 EXIT();
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307664 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307665}
7666
7667#endif /*FEATURE_WLAN_SCAN_PNO*/
7668
7669
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007670#ifdef FEATURE_WLAN_TDLS
7671static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
7672 u8 *peer, u8 action_code, u8 dialog_token,
7673 u16 status_code, const u8 *buf, size_t len)
7674{
7675
7676 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7677 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007678 u8 peerMac[6];
7679 VOS_STATUS status;
Gopichand Nakkala05922802013-03-14 12:23:19 -07007680 int max_sta_failed = 0;
Hoonki Leea34dd892013-02-05 22:56:02 -08007681 int responder;
Hoonki Leed37cbb32013-04-20 00:31:14 -07007682 long rc;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007683
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007684 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007685 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307686 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007687 "Invalid arguments");
7688 return -EINVAL;
7689 }
7690
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08007691 if (pHddCtx->isLogpInProgress)
7692 {
7693 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7694 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07007695 wlan_hdd_tdls_set_link_status(pAdapter, peer, eTDLS_LINK_IDLE);
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08007696 return -EBUSY;
7697 }
7698
Hoonki Lee27511902013-03-14 18:19:06 -07007699 if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007700 {
Hoonki Lee27511902013-03-14 18:19:06 -07007701 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
7702 "%s: TDLS mode is disabled OR not enabled in FW."
7703 MAC_ADDRESS_STR " action %d declined.",
7704 __func__, MAC_ADDR_ARRAY(peer), action_code);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007705 return -ENOTSUPP;
7706 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08007707
Hoonki Lee27511902013-03-14 18:19:06 -07007708 /* other than teardown frame, other mgmt frames are not sent if disabled */
7709 if (SIR_MAC_TDLS_TEARDOWN != action_code)
7710 {
7711 /* if tdls_mode is disabled to respond to peer's request */
7712 if (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode)
7713 {
7714 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
7715 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07007716 " TDLS mode is disabled. action %d declined.",
7717 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee27511902013-03-14 18:19:06 -07007718
7719 return -ENOTSUPP;
7720 }
7721 }
7722
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007723 if (WLAN_IS_TDLS_SETUP_ACTION(action_code))
7724 {
Hoonki Leefb8df672013-04-10 18:20:34 -07007725 if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, peer, TRUE, TRUE))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007726 {
7727 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007728 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07007729 " TDLS setup is ongoing. action %d declined.",
7730 __func__, MAC_ADDR_ARRAY(peer), action_code);
7731 return -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007732 }
7733 }
7734
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007735 if (SIR_MAC_TDLS_SETUP_REQ == action_code ||
7736 SIR_MAC_TDLS_SETUP_RSP == action_code )
Lee Hoonkic1262f22013-01-24 21:59:00 -08007737 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007738 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
Lee Hoonkic1262f22013-01-24 21:59:00 -08007739 {
7740 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
7741 we return error code at 'add_station()'. Hence we have this
7742 check again in addtion to add_station().
7743 Anyway, there is no hard to double-check. */
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007744 if (SIR_MAC_TDLS_SETUP_REQ == action_code)
Lee Hoonkic1262f22013-01-24 21:59:00 -08007745 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007746 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7747 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07007748 " TDLS Max peer already connected. action %d declined.",
7749 __func__, MAC_ADDR_ARRAY(peer), action_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07007750 goto error;
Lee Hoonkic1262f22013-01-24 21:59:00 -08007751 }
7752 else
7753 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007754 /* maximum reached. tweak to send error code to peer and return
7755 error code to supplicant */
Lee Hoonkic1262f22013-01-24 21:59:00 -08007756 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007757 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7758 "%s: " MAC_ADDRESS_STR
7759 " TDLS Max peer already connected send response status %d",
7760 __func__, MAC_ADDR_ARRAY(peer), status_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07007761 max_sta_failed = -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007762 /* fall through to send setup resp with failure status
7763 code */
Lee Hoonkic1262f22013-01-24 21:59:00 -08007764 }
7765 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007766 else
7767 {
7768 hddTdlsPeer_t *pTdlsPeer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007769 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007770 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007771 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007772 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07007773 "%s:" MAC_ADDRESS_STR " already connected. action %d declined.",
7774 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007775 return -EPERM;
7776 }
7777 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08007778 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007779 vos_mem_copy(peerMac, peer, 6);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007780
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007781#ifdef WLAN_FEATURE_TDLS_DEBUG
7782 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007783 "%s: " MAC_ADDRESS_STR " action %d, dialog_token %d status %d, len = %d",
7784 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
7785 action_code, dialog_token, status_code, len);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007786#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007787
Hoonki Leea34dd892013-02-05 22:56:02 -08007788 /*Except teardown responder will not be used so just make 0*/
7789 responder = 0;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007790 if (SIR_MAC_TDLS_TEARDOWN == action_code)
Hoonki Leea34dd892013-02-05 22:56:02 -08007791 {
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -07007792
7793 hddTdlsPeer_t *pTdlsPeer;
7794 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peerMac);
7795
7796 if(pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
7797 responder = pTdlsPeer->is_responder;
7798 else
Hoonki Leea34dd892013-02-05 22:56:02 -08007799 {
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -07007800 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7801 "%s: " MAC_ADDRESS_STR " peer doesn't exist or not connected %d dialog_token %d status %d, len = %d",
7802 __func__, MAC_ADDR_ARRAY(peer), (NULL == pTdlsPeer) ? -1 : pTdlsPeer->link_status,
7803 dialog_token, status_code, len);
7804 return -EPERM;
Hoonki Leea34dd892013-02-05 22:56:02 -08007805 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007806 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007807
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05307808 /* For explicit trigger of DIS_REQ come out of BMPS for
7809 successfully receiving DIS_RSP from peer. */
Hoonki Lee14621352013-04-16 17:51:19 -07007810 if ((SIR_MAC_TDLS_SETUP_RSP == action_code) ||
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05307811 (SIR_MAC_TDLS_DIS_RSP == action_code) ||
7812 (SIR_MAC_TDLS_DIS_REQ == action_code))
Hoonki Lee14621352013-04-16 17:51:19 -07007813 {
7814 if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter)))
7815 {
7816 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05307817 "%s: Sending frame action_code %u.Disable BMPS", __func__, action_code);
Hoonki Lee14621352013-04-16 17:51:19 -07007818 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
7819 }
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05307820 if (SIR_MAC_TDLS_DIS_REQ != action_code)
7821 wlan_hdd_tdls_set_cap(pAdapter, peerMac, eTDLS_CAP_SUPPORTED);
Hoonki Lee14621352013-04-16 17:51:19 -07007822 }
7823
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007824 /* make sure doesn't call send_mgmt() while it is pending */
7825 if (TDLS_CTX_MAGIC == pAdapter->mgmtTxCompletionStatus)
7826 {
7827 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7828 "%s: " MAC_ADDRESS_STR " action %d couldn't sent, as one is pending. return EBUSY\n",
7829 __func__, MAC_ADDR_ARRAY(peer), action_code);
7830 return -EBUSY;
7831 }
7832
7833 pAdapter->mgmtTxCompletionStatus = TDLS_CTX_MAGIC;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007834 INIT_COMPLETION(pAdapter->tdls_mgmt_comp);
7835
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007836 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
Hoonki Leea34dd892013-02-05 22:56:02 -08007837 peerMac, action_code, dialog_token, status_code, (tANI_U8 *)buf, len, responder);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007838
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007839 if (VOS_STATUS_SUCCESS != status)
7840 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007841 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7842 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007843 pAdapter->mgmtTxCompletionStatus = FALSE;
Hoonki Lee14621352013-04-16 17:51:19 -07007844 wlan_hdd_tdls_check_bmps(pAdapter);
7845 goto error;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007846 }
7847
Hoonki Leed37cbb32013-04-20 00:31:14 -07007848 rc = wait_for_completion_interruptible_timeout(&pAdapter->tdls_mgmt_comp,
7849 msecs_to_jiffies(WAIT_TIME_TDLS_MGMT));
7850
7851 if ((rc <= 0) || (TRUE != pAdapter->mgmtTxCompletionStatus))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007852 {
Hoonki Leed37cbb32013-04-20 00:31:14 -07007853 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7854 "%s: Mgmt Tx Completion failed status %ld TxCompletion %lu",
7855 __func__, rc, pAdapter->mgmtTxCompletionStatus);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007856 pAdapter->mgmtTxCompletionStatus = FALSE;
Hoonki Leed37cbb32013-04-20 00:31:14 -07007857 wlan_hdd_tdls_check_bmps(pAdapter);
7858 goto error;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007859 }
7860
Gopichand Nakkala05922802013-03-14 12:23:19 -07007861 if (max_sta_failed)
Hoonki Lee14621352013-04-16 17:51:19 -07007862 {
7863 wlan_hdd_tdls_check_bmps(pAdapter);
Gopichand Nakkala05922802013-03-14 12:23:19 -07007864 return max_sta_failed;
Hoonki Lee14621352013-04-16 17:51:19 -07007865 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007866
Hoonki Leea34dd892013-02-05 22:56:02 -08007867 if (SIR_MAC_TDLS_SETUP_RSP == action_code)
7868 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007869 wlan_hdd_tdls_set_responder(pAdapter, peerMac, TRUE);
Hoonki Leea34dd892013-02-05 22:56:02 -08007870 }
7871 else if (SIR_MAC_TDLS_SETUP_CNF == action_code)
7872 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007873 wlan_hdd_tdls_set_responder(pAdapter, peerMac, FALSE);
Hoonki Leea34dd892013-02-05 22:56:02 -08007874 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007875
7876 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07007877error:
7878 /* max_sta_failed ; we didn't set to CONNECTING for this case,
7879 because we already know that this transaction will be failed,
7880 but we weren't sure if supplicant call DISABLE_LINK or not. So,
7881 to be safe, do not change the state mahine.
7882 */
7883 if(max_sta_failed == 0 &&
7884 (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
7885 wlan_hdd_tdls_set_link_status(pAdapter, peerMac, eTDLS_LINK_IDLE);
7886 return -EPERM;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007887}
7888
7889static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
7890 u8 *peer, enum nl80211_tdls_operation oper)
7891{
7892 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7893 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307894 int status;
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007895#ifdef WLAN_FEATURE_TDLS_DEBUG
7896 const char *tdls_oper_str[]= {
7897 "NL80211_TDLS_DISCOVERY_REQ",
7898 "NL80211_TDLS_SETUP",
7899 "NL80211_TDLS_TEARDOWN",
7900 "NL80211_TDLS_ENABLE_LINK",
7901 "NL80211_TDLS_DISABLE_LINK",
Gopichand Nakkala29d00192013-06-20 19:03:52 +05307902 "NL80211_TDLS_UNKNOWN_OPER"};
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007903#endif
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007904 hddTdlsPeer_t *pTdlsPeer;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007905
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307906 if ( NULL == peer )
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007907 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007908 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Chilam Ngc4244af2013-04-01 15:37:32 -07007909 "%s: Invalid arguments", __func__);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007910 return -EINVAL;
7911 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007912
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307913 status = wlan_hdd_validate_context(pHddCtx);
7914
7915 if (0 != status)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08007916 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307917 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7918 "%s: HDD context is not valid", __func__);
7919 return status;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08007920 }
7921
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007922 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
7923
7924 if ( NULL == pTdlsPeer ) {
7925 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: " MAC_ADDRESS_STR " (oper %d) not exsting. ignored",
7926 __func__, MAC_ADDR_ARRAY(peer), (int)oper);
7927 return -EINVAL;
7928 }
7929
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007930#ifdef WLAN_FEATURE_TDLS_DEBUG
7931 if((int)oper > 4)
7932 oper = 5;
7933
7934 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007935 "%s: " MAC_ADDRESS_STR " link_status %d (%s) ", "tdls_oper",
7936 MAC_ADDR_ARRAY(peer), pTdlsPeer->link_status,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007937 tdls_oper_str[(int)oper]);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007938#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007939
7940 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007941 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007942 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007943 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Chilam Ngc4244af2013-04-01 15:37:32 -07007944 "TDLS Disabled in INI OR not enabled in FW. "
7945 "Cannot process TDLS commands");
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007946 return -ENOTSUPP;
7947 }
7948
7949 switch (oper) {
7950 case NL80211_TDLS_ENABLE_LINK:
7951 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007952 VOS_STATUS status;
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307953 tCsrTdlsLinkEstablishParams tdlsLinkEstablishParams;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007954
Gopichand Nakkala2f4a2822013-04-17 11:22:01 -07007955 if (!TDLS_STA_INDEX_VALID(pTdlsPeer->staId))
7956 {
7957 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Staion Index %u "
7958 MAC_ADDRESS_STR " failed",
7959 __func__, pTdlsPeer->staId, MAC_ADDR_ARRAY(peer));
7960 return -EINVAL;
7961 }
7962
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007963 if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status)
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007964 {
Gopichand Nakkala24be5312013-07-02 16:47:12 +05307965 long ret;
Madan Mohan Koyyalamudice419872013-09-13 19:36:52 +05307966 if (IS_ADVANCE_TDLS_ENABLE) {
Gopichand Nakkala24be5312013-07-02 16:47:12 +05307967
Madan Mohan Koyyalamudice419872013-09-13 19:36:52 +05307968 if (0 != wlan_hdd_tdls_get_link_establish_params(
7969 pAdapter, peer,&tdlsLinkEstablishParams)) {
7970 return -EINVAL;
7971 }
7972 INIT_COMPLETION(pAdapter->tdls_link_establish_req_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307973
Madan Mohan Koyyalamudice419872013-09-13 19:36:52 +05307974 sme_SendTdlsLinkEstablishParams(WLAN_HDD_GET_HAL_CTX(pAdapter),
7975 pAdapter->sessionId, peer, &tdlsLinkEstablishParams);
7976 /* Send TDLS peer UAPSD capabilities to the firmware and
7977 * register with the TL on after the response for this operation
7978 * is received .
7979 */
7980 ret = wait_for_completion_interruptible_timeout(
7981 &pAdapter->tdls_link_establish_req_comp,
7982 msecs_to_jiffies(WAIT_TIME_TDLS_LINK_ESTABLISH_REQ));
7983 if (ret <= 0)
7984 {
7985 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7986 "%s: Link Establish Request Faled Status %ld",
7987 __func__, ret);
7988 return -EINVAL;
7989 }
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307990 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007991 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
Gopichand Nakkala471708b2013-06-04 20:03:01 +05307992 /* Mark TDLS client Authenticated .*/
7993 status = WLANTL_ChangeSTAState( pHddCtx->pvosContext,
7994 pTdlsPeer->staId,
7995 WLANTL_STA_AUTHENTICATED);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007996 if (VOS_STATUS_SUCCESS == status)
7997 {
Hoonki Lee14621352013-04-16 17:51:19 -07007998 if (pTdlsPeer->is_responder == 0)
7999 {
8000 v_U8_t staId = (v_U8_t)pTdlsPeer->staId;
8001
8002 wlan_hdd_tdls_timer_restart(pAdapter,
8003 &pTdlsPeer->initiatorWaitTimeoutTimer,
8004 WAIT_TIME_TDLS_INITIATOR);
8005 /* suspend initiator TX until it receives direct packet from the
8006 reponder or WAIT_TIME_TDLS_INITIATOR timer expires */
8007 WLANTL_SuspendDataTx( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
8008 &staId, NULL);
8009 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07008010 wlan_hdd_tdls_increment_peer_count(pAdapter);
8011 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008012 wlan_hdd_tdls_check_bmps(pAdapter);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308013
8014 /* Update TL about the UAPSD masks , to route the packets to firmware */
Gopichand Nakkala574f6d12013-06-27 19:38:43 +05308015 if ((TRUE == pHddCtx->cfg_ini->fEnableTDLSBufferSta)
8016 || pHddCtx->cfg_ini->fTDLSUapsdMask )
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308017 {
Gopichand Nakkala574f6d12013-06-27 19:38:43 +05308018 int ac;
8019 uint8 ucAc[4] = { WLANTL_AC_VO,
8020 WLANTL_AC_VI,
8021 WLANTL_AC_BK,
8022 WLANTL_AC_BE };
8023 uint8 tlTid[4] = { 7, 5, 2, 3 } ;
8024 for(ac=0; ac < 4; ac++)
8025 {
8026 status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
8027 pTdlsPeer->staId, ucAc[ac],
8028 tlTid[ac], tlTid[ac], 0, 0,
8029 WLANTL_BI_DIR );
8030 }
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308031 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008032 }
8033
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008034 }
8035 break;
8036 case NL80211_TDLS_DISABLE_LINK:
Lee Hoonkic1262f22013-01-24 21:59:00 -08008037 {
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008038 if(TDLS_STA_INDEX_VALID(pTdlsPeer->staId))
Lee Hoonkic1262f22013-01-24 21:59:00 -08008039 {
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07008040 long status;
8041
8042 INIT_COMPLETION(pAdapter->tdls_del_station_comp);
8043
Lee Hoonkic1262f22013-01-24 21:59:00 -08008044 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
8045 pAdapter->sessionId, peer );
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07008046
8047 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_del_station_comp,
8048 msecs_to_jiffies(WAIT_TIME_TDLS_DEL_STA));
8049 if (status <= 0)
8050 {
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008051 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_IDLE);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07008052 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8053 "%s: Del station failed status %ld",
8054 __func__, status);
8055 return -EPERM;
8056 }
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008057 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_IDLE);
Lee Hoonkic1262f22013-01-24 21:59:00 -08008058 }
8059 else
8060 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008061 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8062 "%s: TDLS Peer Station doesn't exist.", __func__);
Lee Hoonkic1262f22013-01-24 21:59:00 -08008063 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08008064 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008065 break;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008066 case NL80211_TDLS_TEARDOWN:
8067 case NL80211_TDLS_SETUP:
8068 case NL80211_TDLS_DISCOVERY_REQ:
8069 /* We don't support in-driver setup/teardown/discovery */
8070 return -ENOTSUPP;
8071 default:
8072 return -ENOTSUPP;
8073 }
8074 return 0;
8075}
Chilam NG571c65a2013-01-19 12:27:36 +05308076
8077int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
8078 struct net_device *dev, u8 *peer)
8079{
8080 hddLog(VOS_TRACE_LEVEL_INFO, "tdls send discover req: %x %x %x %x %x %x",
8081 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5]);
8082
8083 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
8084 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
8085}
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008086#endif
8087
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308088#ifdef WLAN_FEATURE_GTK_OFFLOAD
8089/*
8090 * FUNCTION: wlan_hdd_cfg80211_update_replayCounterCallback
8091 * Callback rountine called upon receiving response for
8092 * get offload info
8093 */
8094void wlan_hdd_cfg80211_update_replayCounterCallback(void *callbackContext,
8095 tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoRsp)
8096{
8097
8098 hdd_adapter_t *pAdapter = (hdd_adapter_t *)callbackContext;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308099 tANI_U8 tempReplayCounter[8];
8100 hdd_station_ctx_t *pHddStaCtx;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308101
8102 ENTER();
8103
8104 if (NULL == pAdapter)
8105 {
8106 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8107 "%s: HDD adapter is Null", __func__);
8108 return ;
8109 }
8110
8111 if (NULL == pGtkOffloadGetInfoRsp)
8112 {
8113 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8114 "%s: pGtkOffloadGetInfoRsp is Null", __func__);
8115 return ;
8116 }
8117
8118 if (VOS_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus)
8119 {
8120 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8121 "%s: wlan Failed to get replay counter value",
8122 __func__);
8123 return ;
8124 }
8125
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308126 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8127 /* Update replay counter */
8128 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
8129 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
8130
8131 {
8132 /* changing from little to big endian since supplicant
8133 * works on big endian format
8134 */
8135 int i;
8136 tANI_U8 *p = (tANI_U8 *)&pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
8137
8138 for (i = 0; i < 8; i++)
8139 {
8140 tempReplayCounter[7-i] = (tANI_U8)p[i];
8141 }
8142 }
8143
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308144 /* Update replay counter to NL */
8145 cfg80211_gtk_rekey_notify(pAdapter->dev, pGtkOffloadGetInfoRsp->bssId,
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308146 tempReplayCounter, GFP_KERNEL);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308147}
8148
8149/*
8150 * FUNCTION: wlan_hdd_cfg80211_set_rekey_data
8151 * This function is used to offload GTK rekeying job to the firmware.
8152 */
8153int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
8154 struct cfg80211_gtk_rekey_data *data)
8155{
8156 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8157 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8158 hdd_station_ctx_t *pHddStaCtx;
8159 tHalHandle hHal;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308160 int result;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308161 tSirGtkOffloadParams hddGtkOffloadReqParams;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308162 eHalStatus status = eHAL_STATUS_FAILURE;
8163
8164 ENTER();
8165
8166 if (NULL == pAdapter)
8167 {
8168 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8169 "%s: HDD adapter is Null", __func__);
8170 return -ENODEV;
8171 }
8172
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308173 result = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308174
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308175 if (0 != result)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308176 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308177 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8178 "%s: HDD context is not valid", __func__);
8179 return result;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308180 }
8181
8182 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8183 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8184 if (NULL == hHal)
8185 {
8186 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8187 "%s: HAL context is Null!!!", __func__);
8188 return -EAGAIN;
8189 }
8190
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308191 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
8192 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck, NL80211_KCK_LEN);
8193 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek, NL80211_KEK_LEN);
8194 memcpy(pHddStaCtx->gtkOffloadReqParams.bssId, &pHddStaCtx->conn_info.bssId,
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308195 WNI_CFG_BSSID_LEN);
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308196 {
8197 /* changing from big to little endian since driver
8198 * works on little endian format
8199 */
8200 tANI_U8 *p =
8201 (tANI_U8 *)&pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter;
8202 int i;
8203
8204 for (i = 0; i < 8; i++)
8205 {
8206 p[7-i] = data->replay_ctr[i];
8207 }
8208 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308209
8210 if (TRUE == pHddCtx->hdd_wlan_suspended)
8211 {
8212 /* if wlan is suspended, enable GTK offload directly from here */
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308213 memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams,
8214 sizeof (tSirGtkOffloadParams));
8215 status = sme_SetGTKOffload(hHal, &hddGtkOffloadReqParams,
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308216 pAdapter->sessionId);
8217
8218 if (eHAL_STATUS_SUCCESS != status)
8219 {
8220 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8221 "%s: sme_SetGTKOffload failed, returned %d",
8222 __func__, status);
8223 return status;
8224 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308225 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8226 "%s: sme_SetGTKOffload successfull", __func__);
8227 }
8228 else
8229 {
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308230 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8231 "%s: wlan not suspended GTKOffload request is stored",
8232 __func__);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308233 }
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308234
8235 return eHAL_STATUS_SUCCESS;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308236}
8237#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
8238
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05308239/*
8240 * FUNCTION: wlan_hdd_cfg80211_set_mac_acl
8241 * This function is used to set access control policy
8242 */
8243static int wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
8244 struct net_device *dev, const struct cfg80211_acl_data *params)
8245{
8246 int i;
8247 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8248 hdd_hostapd_state_t *pHostapdState;
8249 tsap_Config_t *pConfig;
8250 v_CONTEXT_t pVosContext = NULL;
8251 hdd_context_t *pHddCtx;
8252 int status;
8253
8254 ENTER();
8255
8256 if (NULL == pAdapter)
8257 {
8258 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8259 "%s: HDD adapter is Null", __func__);
8260 return -ENODEV;
8261 }
8262
8263 if (NULL == params)
8264 {
8265 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8266 "%s: params is Null", __func__);
8267 return -EINVAL;
8268 }
8269
8270 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8271 status = wlan_hdd_validate_context(pHddCtx);
8272
8273 if (0 != status)
8274 {
8275 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8276 "%s: HDD context is not valid", __func__);
8277 return status;
8278 }
8279
8280 pVosContext = pHddCtx->pvosContext;
8281 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
8282
8283 if (NULL == pHostapdState)
8284 {
8285 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8286 "%s: pHostapdState is Null", __func__);
8287 return -EINVAL;
8288 }
8289
8290 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"acl policy: = %d"
8291 "no acl entries = %d", params->acl_policy, params->n_acl_entries);
8292
8293 if (WLAN_HDD_SOFTAP == pAdapter->device_mode)
8294 {
8295 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
8296
8297 /* default value */
8298 pConfig->num_accept_mac = 0;
8299 pConfig->num_deny_mac = 0;
8300
8301 /**
8302 * access control policy
8303 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
8304 * listed in hostapd.deny file.
8305 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
8306 * listed in hostapd.accept file.
8307 */
8308 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy)
8309 {
8310 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
8311 }
8312 else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED == params->acl_policy)
8313 {
8314 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
8315 }
8316 else
8317 {
8318 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8319 "%s:Acl Policy : %d is not supported",
8320 __func__, params->acl_policy);
8321 return -ENOTSUPP;
8322 }
8323
8324 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl)
8325 {
8326 pConfig->num_accept_mac = params->n_acl_entries;
8327 for (i = 0; i < params->n_acl_entries; i++)
8328 {
8329 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8330 "** Add ACL MAC entry %i in WhiletList :"
8331 MAC_ADDRESS_STR, i,
8332 MAC_ADDR_ARRAY(params->mac_addrs[i].addr));
8333
8334 vos_mem_copy(&pConfig->accept_mac[i], params->mac_addrs[i].addr,
8335 sizeof(qcmacaddr));
8336 }
8337 }
8338 else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl)
8339 {
8340 pConfig->num_deny_mac = params->n_acl_entries;
8341 for (i = 0; i < params->n_acl_entries; i++)
8342 {
8343 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8344 "** Add ACL MAC entry %i in BlackList :"
8345 MAC_ADDRESS_STR, i,
8346 MAC_ADDR_ARRAY(params->mac_addrs[i].addr));
8347
8348 vos_mem_copy(&pConfig->deny_mac[i], params->mac_addrs[i].addr,
8349 sizeof(qcmacaddr));
8350 }
8351 }
8352
8353 if (VOS_STATUS_SUCCESS != WLANSAP_SetMacACL(pVosContext, pConfig))
8354 {
8355 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8356 "%s: SAP Set Mac Acl fail", __func__);
8357 return -EINVAL;
8358 }
8359 }
8360 else
8361 {
8362 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8363 "%s: Invalid device_mode = %d",
8364 __func__, pAdapter->device_mode);
8365 return -EINVAL;
8366 }
8367
8368 return 0;
8369}
8370
Leo Chang9056f462013-08-01 19:21:11 -07008371#ifdef WLAN_NL80211_TESTMODE
8372#ifdef FEATURE_WLAN_LPHB
8373static void wlan_hdd_cfg80211_lphb_wait_timeout_ind_handler
8374(
8375 void *pAdapter,
8376 void *indCont
8377)
8378{
8379 tSirLPHBTimeoutInd *lphbTimeoutInd;
8380 struct sk_buff *skb;
8381
8382 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8383 "LPHB wait timeout indication arrived");
8384
8385 if (NULL == indCont)
8386 {
8387 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8388 "LPHB timeout, invalid argument");
8389 return;
8390 }
8391
8392 lphbTimeoutInd = (tSirLPHBTimeoutInd *)indCont;
8393 skb = cfg80211_testmode_alloc_event_skb(
8394 ((hdd_adapter_t *)pAdapter)->wdev.wiphy,
8395 sizeof(tSirLPHBTimeoutInd),
8396 GFP_ATOMIC);
8397 if (!skb)
8398 {
8399 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8400 "LPHB timeout, NL buffer alloc fail");
8401 return;
8402 }
8403
8404 NLA_PUT_U32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB);
8405 NLA_PUT_U32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbTimeoutInd->protocolType);
8406 NLA_PUT(skb, WLAN_HDD_TM_ATTR_DATA,
8407 sizeof(tSirLPHBTimeoutInd), lphbTimeoutInd);
8408 cfg80211_testmode_event(skb, GFP_ATOMIC);
8409 return;
8410
8411nla_put_failure:
8412 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8413 "NLA Put fail");
8414 kfree_skb(skb);
8415
8416 return;
8417}
8418#endif /* FEATURE_WLAN_LPHB */
8419
8420static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy, void *data, int len)
8421{
8422 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
8423 int err = 0;
8424#ifdef FEATURE_WLAN_LPHB
8425 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8426#endif /* FEATURE_WLAN_LPHB */
8427
8428 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data, len, wlan_hdd_tm_policy);
8429 if (err)
8430 {
8431 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8432 "%s Testmode INV ATTR", __func__);
8433 return err;
8434 }
8435
8436 if (!tb[WLAN_HDD_TM_ATTR_CMD])
8437 {
8438 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8439 "%s Testmode INV CMD", __func__);
8440 return -EINVAL;
8441 }
8442
8443 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]))
8444 {
8445#ifdef FEATURE_WLAN_LPHB
8446 /* Low Power Heartbeat configuration request */
8447 case WLAN_HDD_TM_CMD_WLAN_HB:
8448 {
8449 int buf_len;
8450 void *buf;
8451 tSirLPHBReq *hb_params = NULL;
8452
8453 if (!tb[WLAN_HDD_TM_ATTR_DATA])
8454 {
8455 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8456 "%s Testmode INV DATA", __func__);
8457 return -EINVAL;
8458 }
8459
8460 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
8461 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
8462 hb_params = (tSirLPHBReq *)vos_mem_malloc(sizeof(tSirLPHBReq));
8463 if (NULL == hb_params)
8464 {
8465 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8466 "%s Request Buffer Alloc Fail", __func__);
8467 return -EINVAL;
8468 }
8469
8470 vos_mem_copy(hb_params, buf, buf_len);
8471
8472 /* LPHB enable and disable request will send to FW
8473 * when host suspend and resume
8474 * host suspend -> enable LPHB
8475 * host resume -> disable LPHB
8476 * if host is not suspend, cache into HDD context
8477 * and when host goes to suspend, send request to FW */
8478 if ((LPHB_SET_EN_PARAMS_INDID == hb_params->cmd) &&
8479 (!pHddCtx->hdd_wlan_suspended))
8480 {
8481 /* Feature enable command cache into HDD context,
8482 * if WLAN is not suspend
8483 * When WLAN goes into suspend, send enable command to FW */
8484 pHddCtx->lphbEnableReq.enable =
8485 hb_params->params.lphbEnableReq.enable;
8486 pHddCtx->lphbEnableReq.item =
8487 hb_params->params.lphbEnableReq.item;
8488 pHddCtx->lphbEnableReq.session =
8489 hb_params->params.lphbEnableReq.session;
8490 vos_mem_free(hb_params);
8491 }
8492 else
8493 {
8494 eHalStatus smeStatus;
8495
8496 /* If WLAN is suspend state, send enable command immediately */
8497 smeStatus = sme_LPHBConfigReq((tHalHandle)(pHddCtx->hHal),
8498 hb_params,
8499 wlan_hdd_cfg80211_lphb_wait_timeout_ind_handler);
8500 if (eHAL_STATUS_SUCCESS != smeStatus)
8501 {
8502 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8503 "LPHB Config Fail, disable");
8504 pHddCtx->lphbEnableReq.enable = 0;
8505 vos_mem_free(hb_params);
8506 }
8507 }
8508 return 0;
8509 }
8510#endif /* FEATURE_WLAN_LPHB */
8511 default:
8512 return -EOPNOTSUPP;
8513 }
8514
8515 return err;
8516}
8517#endif /* CONFIG_NL80211_TESTMODE */
8518
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308519static int wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy,
8520 struct net_device *dev,
8521 int idx, struct survey_info *survey)
8522{
8523 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8524 hdd_context_t *pHddCtx;
Mihir Sheted9072e02013-08-21 17:02:29 +05308525 hdd_station_ctx_t *pHddStaCtx;
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308526 tHalHandle halHandle;
Mihir Sheted9072e02013-08-21 17:02:29 +05308527 v_U32_t channel = 0, freq = 0; /* Initialization Required */
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308528 v_S7_t snr,rssi;
8529 int status, i, j, filled = 0;
8530
8531 ENTER();
8532
8533
8534 if (NULL == pAdapter)
8535 {
8536 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8537 "%s: HDD adapter is Null", __func__);
8538 return -ENODEV;
8539 }
8540
8541 if (NULL == wiphy)
8542 {
8543 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8544 "%s: wiphy is Null", __func__);
8545 return -ENODEV;
8546 }
8547
8548 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8549 status = wlan_hdd_validate_context(pHddCtx);
8550
8551 if (0 != status)
8552 {
8553 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8554 "%s: HDD context is not valid", __func__);
8555 return status;
8556 }
8557
Mihir Sheted9072e02013-08-21 17:02:29 +05308558 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8559
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308560 if (0 == pHddCtx->cfg_ini->fEnableSNRMonitoring ||
Mihir Sheted9072e02013-08-21 17:02:29 +05308561 0 != pAdapter->survey_idx ||
8562 eConnectionState_Associated != pHddStaCtx->conn_info.connState)
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308563 {
8564 /* The survey dump ops when implemented completely is expected to
8565 * return a survey of all channels and the ops is called by the
8566 * kernel with incremental values of the argument 'idx' till it
8567 * returns -ENONET. But we can only support the survey for the
8568 * operating channel for now. survey_idx is used to track
8569 * that the ops is called only once and then return -ENONET for
8570 * the next iteration
8571 */
8572 pAdapter->survey_idx = 0;
8573 return -ENONET;
8574 }
8575
8576 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
8577
8578 wlan_hdd_get_snr(pAdapter, &snr);
8579 wlan_hdd_get_rssi(pAdapter, &rssi);
8580
8581 sme_GetOperationChannel(halHandle, &channel, pAdapter->sessionId);
8582 hdd_wlan_get_freq(channel, &freq);
8583
8584
8585 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
8586 {
8587 if (NULL == wiphy->bands[i])
8588 {
8589 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
8590 "%s: wiphy->bands[i] is NULL, i = %d", __func__, i);
8591 continue;
8592 }
8593
8594 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
8595 {
8596 struct ieee80211_supported_band *band = wiphy->bands[i];
8597
8598 if (band->channels[j].center_freq == (v_U16_t)freq)
8599 {
8600 survey->channel = &band->channels[j];
8601 /* The Rx BDs contain SNR values in dB for the received frames
8602 * while the supplicant expects noise. So we calculate and
8603 * return the value of noise (dBm)
8604 * SNR (dB) = RSSI (dBm) - NOISE (dBm)
8605 */
8606 survey->noise = rssi - snr;
8607 survey->filled = SURVEY_INFO_NOISE_DBM;
8608 filled = 1;
8609 }
8610 }
8611 }
8612
8613 if (filled)
8614 pAdapter->survey_idx = 1;
8615 else
8616 {
8617 pAdapter->survey_idx = 0;
8618 return -ENONET;
8619 }
8620
8621 return 0;
8622}
8623
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308624/*
8625 * FUNCTION: wlan_hdd_cfg80211_resume_wlan
8626 * this is called when cfg80211 driver resume
8627 * driver updates latest sched_scan scan result(if any) to cfg80211 database
8628 */
8629int wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
8630{
8631 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8632 hdd_adapter_t *pAdapter;
8633 hdd_adapter_list_node_t *pAdapterNode, *pNext;
8634 VOS_STATUS status = VOS_STATUS_SUCCESS;
8635
8636 ENTER();
8637
8638 if ( NULL == pHddCtx )
8639 {
8640 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8641 "%s: HddCtx validation failed", __func__);
8642 return 0;
8643 }
8644
8645 if (pHddCtx->isLogpInProgress)
8646 {
8647 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8648 "%s: LOGP in Progress. Ignore!!!", __func__);
8649 return 0;
8650 }
8651
8652 if (pHddCtx->isLoadUnloadInProgress)
8653 {
8654 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8655 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
8656 return 0;
8657 }
8658
8659 spin_lock(&pHddCtx->schedScan_lock);
8660 pHddCtx->isWiphySuspended = FALSE;
8661 if (TRUE != pHddCtx->isSchedScanUpdatePending)
8662 {
8663 spin_unlock(&pHddCtx->schedScan_lock);
8664 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8665 "%s: Return resume is not due to PNO indication", __func__);
8666 return 0;
8667 }
8668 // Reset flag to avoid updatating cfg80211 data old results again
8669 pHddCtx->isSchedScanUpdatePending = FALSE;
8670 spin_unlock(&pHddCtx->schedScan_lock);
8671
8672 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8673
8674 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
8675 {
8676 pAdapter = pAdapterNode->pAdapter;
8677 if ( (NULL != pAdapter) &&
8678 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
8679 {
8680 if (0 != wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter))
8681 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
8682 "%s: NO SCAN result", __func__);
8683 else
8684 cfg80211_sched_scan_results(pHddCtx->wiphy);
8685
8686 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8687 "%s : cfg80211 scan result database updated", __func__);
8688
8689 return 0;
8690
8691 }
8692 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8693 pAdapterNode = pNext;
8694 }
8695
8696 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8697 "%s: Failed to find Adapter", __func__);
8698 return 0;
8699}
8700
8701/*
8702 * FUNCTION: wlan_hdd_cfg80211_suspend_wlan
8703 * this is called when cfg80211 driver suspends
8704 */
8705int wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
8706 struct cfg80211_wowlan *wow)
8707{
8708 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8709
8710 ENTER();
8711 if (NULL == pHddCtx)
8712 {
8713 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8714 "%s: HddCtx validation failed", __func__);
8715 return 0;
8716 }
8717
8718 pHddCtx->isWiphySuspended = TRUE;
8719
8720 EXIT();
8721
8722 return 0;
8723}
8724
Jeff Johnson295189b2012-06-20 16:38:30 -07008725/* cfg80211_ops */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308726static struct cfg80211_ops wlan_hdd_cfg80211_ops =
Jeff Johnson295189b2012-06-20 16:38:30 -07008727{
8728 .add_virtual_intf = wlan_hdd_add_virtual_intf,
8729 .del_virtual_intf = wlan_hdd_del_virtual_intf,
8730 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
8731 .change_station = wlan_hdd_change_station,
8732#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
8733 .add_beacon = wlan_hdd_cfg80211_add_beacon,
8734 .del_beacon = wlan_hdd_cfg80211_del_beacon,
8735 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008736#else
8737 .start_ap = wlan_hdd_cfg80211_start_ap,
8738 .change_beacon = wlan_hdd_cfg80211_change_beacon,
8739 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07008740#endif
8741 .change_bss = wlan_hdd_cfg80211_change_bss,
8742 .add_key = wlan_hdd_cfg80211_add_key,
8743 .get_key = wlan_hdd_cfg80211_get_key,
8744 .del_key = wlan_hdd_cfg80211_del_key,
8745 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08008746#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07008747 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08008748#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008749 .scan = wlan_hdd_cfg80211_scan,
8750 .connect = wlan_hdd_cfg80211_connect,
8751 .disconnect = wlan_hdd_cfg80211_disconnect,
8752 .join_ibss = wlan_hdd_cfg80211_join_ibss,
8753 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
8754 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
8755 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
8756 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
Jeff Johnson295189b2012-06-20 16:38:30 -07008757 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
8758 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
8759 .mgmt_tx = wlan_hdd_action,
8760#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
8761 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
8762 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
8763 .set_txq_params = wlan_hdd_set_txq_params,
8764#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008765 .get_station = wlan_hdd_cfg80211_get_station,
8766 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
8767 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008768 .add_station = wlan_hdd_cfg80211_add_station,
8769#ifdef FEATURE_WLAN_LFR
8770 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
8771 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
8772 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
8773#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07008774#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
8775 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
8776#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008777#ifdef FEATURE_WLAN_TDLS
8778 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
8779 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
8780#endif
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308781#ifdef WLAN_FEATURE_GTK_OFFLOAD
8782 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
8783#endif /* WLAN_FEATURE_GTK_OFFLOAD */
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308784#ifdef FEATURE_WLAN_SCAN_PNO
8785 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
8786 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
8787#endif /*FEATURE_WLAN_SCAN_PNO */
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308788 .resume = wlan_hdd_cfg80211_resume_wlan,
8789 .suspend = wlan_hdd_cfg80211_suspend_wlan,
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05308790 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
Leo Chang9056f462013-08-01 19:21:11 -07008791#ifdef WLAN_NL80211_TESTMODE
8792 .testmode_cmd = wlan_hdd_cfg80211_testmode,
8793#endif
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308794 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Jeff Johnson295189b2012-06-20 16:38:30 -07008795};
8796