blob: f925dd96ad62b24eec9d90b18576115a76917d12 [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
Amar Singhala49cbc52013-10-08 18:37:44 -0700642 wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
643
644
Amar Singhalfddc28c2013-09-05 13:03:40 -0700645 /* This will disable updating of NL channels from passive to
646 * active if a beacon is received on passive channel. */
647 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhalf0073192013-09-20 12:34:56 -0700648
Amar Singhalfddc28c2013-09-05 13:03:40 -0700649
Amar Singhala49cbc52013-10-08 18:37:44 -0700650
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700651#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700652 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
653 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
654 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
Jeff Johnsone7245742012-09-05 17:12:55 -0700655 | WIPHY_FLAG_OFFCHAN_TX;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700656#endif
Amar Singhala49cbc52013-10-08 18:37:44 -0700657
Srinivas Girigowda640728a2013-03-28 12:21:54 -0700658#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
659 if (pCfg->isFastTransitionEnabled
James Zmuda77fb5ae2013-01-29 08:00:17 -0800660#ifdef FEATURE_WLAN_LFR
Srinivas Girigowda640728a2013-03-28 12:21:54 -0700661 || pCfg->isFastRoamIniFeatureEnabled
662#endif
663#ifdef FEATURE_WLAN_CCX
664 || pCfg->isCcxIniFeatureEnabled
665#endif
666 )
667 {
668 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
669 }
James Zmuda77fb5ae2013-01-29 08:00:17 -0800670#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800671#ifdef FEATURE_WLAN_TDLS
672 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
673 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
674#endif
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +0530675#ifdef FEATURE_WLAN_SCAN_PNO
676 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
Madan Mohan Koyyalamudi75de0102013-09-17 14:56:29 +0530677 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +0530678 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
Madan Mohan Koyyalamudia7765d52013-09-18 16:49:56 +0530679 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +0530680#endif/*FEATURE_WLAN_SCAN_PNO*/
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800681
Amar Singhalfddc28c2013-09-05 13:03:40 -0700682#ifdef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700683 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
684 driver can still register regulatory callback and
Amar Singhalfddc28c2013-09-05 13:03:40 -0700685 it will get regulatory settings in wiphy->band[], but
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700686 driver need to determine what to do with both
687 regulatory settings */
Amar Singhalfddc28c2013-09-05 13:03:40 -0700688
689 wiphy->reg_notifier = wlan_hdd_linux_reg_notifier;
Amar Singhala49cbc52013-10-08 18:37:44 -0700690#else
691 wiphy->reg_notifier = wlan_hdd_crda_reg_notifier;
Amar Singhalfddc28c2013-09-05 13:03:40 -0700692#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700693
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530694 wiphy->max_scan_ssids = MAX_SCAN_SSID;
695
Madan Mohan Koyyalamudi6815b162013-07-19 17:17:46 +0530696 wiphy->max_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Jeff Johnson295189b2012-06-20 16:38:30 -0700697
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +0530698 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
699
Jeff Johnson295189b2012-06-20 16:38:30 -0700700 /* Supports STATION & AD-HOC modes right now */
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530701 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -0700702 | BIT(NL80211_IFTYPE_ADHOC)
Jeff Johnson295189b2012-06-20 16:38:30 -0700703 | BIT(NL80211_IFTYPE_P2P_CLIENT)
704 | BIT(NL80211_IFTYPE_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -0700705 | BIT(NL80211_IFTYPE_AP);
706
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800707#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800708 if( pCfg->enableMCC )
709 {
710 /* Currently, supports up to two channels */
711 wlan_hdd_iface_combination.num_different_channels = 2;
712
713 if( !pCfg->allowMCCGODiffBI )
714 wlan_hdd_iface_combination.beacon_int_infra_match = true;
715
716 }
717 wiphy->iface_combinations = &wlan_hdd_iface_combination;
718 wiphy->n_iface_combinations = 1;
719#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800720
Jeff Johnson295189b2012-06-20 16:38:30 -0700721 /* Before registering we need to update the ht capabilitied based
722 * on ini values*/
723 if( !pCfg->ShortGI20MhzEnable )
724 {
725 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
726 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
727 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
728 }
729
730 if( !pCfg->ShortGI40MhzEnable )
731 {
732 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
733 }
734
735 if( !pCfg->nChannelBondingMode5GHz )
736 {
737 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
738 }
739
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530740 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
741 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
742
743 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
744 {
745
746 if (NULL == wiphy->bands[i])
747 {
748 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[i] is NULL, i = %d",
749 __func__, i);
750 continue;
751 }
752
753 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
754 {
755 struct ieee80211_supported_band *band = wiphy->bands[i];
756
757 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == pCfg->nBandCapability) // 5G only
758 {
759 // Enable social channels for P2P
760 if (WLAN_HDD_IS_SOCIAL_CHANNEL(band->channels[j].center_freq))
761 band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED;
762 else
763 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
764 continue;
765 }
766 else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == pCfg->nBandCapability) // 2G only
767 {
768 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
769 continue;
770 }
771 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700772 }
773 /*Initialise the supported cipher suite details*/
774 wiphy->cipher_suites = hdd_cipher_suites;
775 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
776
777 /*signal strength in mBm (100*dBm) */
778 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
779
780#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -0700781 wiphy->max_remain_on_channel_duration = 1000;
782#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700783
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530784 EXIT();
785 return 0;
786}
787
788/* In this function we are registering wiphy. */
789int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
790{
791 ENTER();
792 /* Register our wiphy dev with cfg80211 */
Jeff Johnson295189b2012-06-20 16:38:30 -0700793 if (0 > wiphy_register(wiphy))
794 {
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530795 /* print error */
Jeff Johnson295189b2012-06-20 16:38:30 -0700796 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
797 return -EIO;
798 }
799
800 EXIT();
801 return 0;
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530802}
Jeff Johnson295189b2012-06-20 16:38:30 -0700803
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530804/* In this function we are updating channel list when,
805 regulatory domain is FCC and country code is US.
806 Here In FCC standard 5GHz UNII-1 Bands are indoor only.
807 As per FCC smart phone is not a indoor device.
808 GO should not opeate on indoor channels */
809void wlan_hdd_cfg80211_update_reg_info(struct wiphy *wiphy)
810{
811 int j;
812 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
813 tANI_U8 defaultCountryCode[3] = SME_INVALID_COUNTRY_CODE;
814 //Default counrtycode from NV at the time of wiphy initialization.
815 if (eHAL_STATUS_SUCCESS != sme_GetDefaultCountryCodeFrmNv(pHddCtx->hHal,
816 &defaultCountryCode[0]))
817 {
818 hddLog(LOGE, FL("%s Failed to get default country code from NV"));
819 }
820 if ((defaultCountryCode[0]== 'U') && (defaultCountryCode[1]=='S'))
821 {
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530822 if (NULL == wiphy->bands[IEEE80211_BAND_5GHZ])
823 {
824 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[IEEE80211_BAND_5GHZ] is NULL",__func__ );
825 return;
826 }
827 for (j = 0; j < wiphy->bands[IEEE80211_BAND_5GHZ]->n_channels; j++)
828 {
829 struct ieee80211_supported_band *band = wiphy->bands[IEEE80211_BAND_5GHZ];
830 // Mark UNII -1 band channel as passive
831 if (WLAN_HDD_CHANNEL_IN_UNII_1_BAND(band->channels[j].center_freq))
832 band->channels[j].flags |= IEEE80211_CHAN_PASSIVE_SCAN;
833 }
834 }
835}
836
Jeff Johnson295189b2012-06-20 16:38:30 -0700837/* In this function we will do all post VOS start initialization.
838 In this function we will register for all frame in which supplicant
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530839 is interested.
Jeff Johnson295189b2012-06-20 16:38:30 -0700840*/
841void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
842{
Jeff Johnson295189b2012-06-20 16:38:30 -0700843 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
844 /* Register for all P2P action, public action etc frames */
845 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
846
Jeff Johnsone7245742012-09-05 17:12:55 -0700847 ENTER();
848
Jeff Johnson295189b2012-06-20 16:38:30 -0700849 /* Right now we are registering these frame when driver is getting
850 initialized. Once we will move to 2.6.37 kernel, in which we have
851 frame register ops, we will move this code as a part of that */
852 /* GAS Initial Request */
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530853 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
Jeff Johnson295189b2012-06-20 16:38:30 -0700854 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
855
856 /* GAS Initial Response */
857 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
858 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530859
Jeff Johnson295189b2012-06-20 16:38:30 -0700860 /* GAS Comeback Request */
861 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
862 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
863
864 /* GAS Comeback Response */
865 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
866 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
867
868 /* P2P Public Action */
869 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530870 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
Jeff Johnson295189b2012-06-20 16:38:30 -0700871 P2P_PUBLIC_ACTION_FRAME_SIZE );
872
873 /* P2P Action */
874 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
875 (v_U8_t*)P2P_ACTION_FRAME,
876 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -0700877
Gopichand Nakkalae3d56e72013-04-21 23:33:32 +0530878 /* WNM BSS Transition Request frame */
879 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
880 (v_U8_t*)WNM_BSS_ACTION_FRAME,
881 WNM_BSS_ACTION_FRAME_SIZE );
882
Chet Lanctot186b5732013-03-18 10:26:30 -0700883#ifdef WLAN_FEATURE_11W
884 /* SA Query Response Action Frame */
885 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
886 (v_U8_t*)SA_QUERY_FRAME_RSP,
887 SA_QUERY_FRAME_RSP_SIZE );
888#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -0700889}
890
891void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
892{
Jeff Johnson295189b2012-06-20 16:38:30 -0700893 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
894 /* Register for all P2P action, public action etc frames */
895 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
896
Jeff Johnsone7245742012-09-05 17:12:55 -0700897 ENTER();
898
Jeff Johnson295189b2012-06-20 16:38:30 -0700899 /* Right now we are registering these frame when driver is getting
900 initialized. Once we will move to 2.6.37 kernel, in which we have
901 frame register ops, we will move this code as a part of that */
902 /* GAS Initial Request */
903
904 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
905 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
906
907 /* GAS Initial Response */
908 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
909 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530910
Jeff Johnson295189b2012-06-20 16:38:30 -0700911 /* GAS Comeback Request */
912 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
913 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
914
915 /* GAS Comeback Response */
916 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
917 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
918
919 /* P2P Public Action */
920 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530921 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
Jeff Johnson295189b2012-06-20 16:38:30 -0700922 P2P_PUBLIC_ACTION_FRAME_SIZE );
923
924 /* P2P Action */
925 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
926 (v_U8_t*)P2P_ACTION_FRAME,
927 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -0700928
929#ifdef WLAN_FEATURE_11W
930 /* SA Query Response Action Frame */
931 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
932 (v_U8_t*)SA_QUERY_FRAME_RSP,
933 SA_QUERY_FRAME_RSP_SIZE );
934#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -0700935}
936
937#ifdef FEATURE_WLAN_WAPI
938void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
939 const u8 *mac_addr, u8 *key , int key_Len)
940{
941 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
942 tCsrRoamSetKey setKey;
943 v_BOOL_t isConnected = TRUE;
944 int status = 0;
945 v_U32_t roamId= 0xFF;
946 tANI_U8 *pKeyPtr = NULL;
947 int n = 0;
948
949 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
950 __func__,pAdapter->device_mode);
951
Gopichand Nakkalae7480202013-02-11 15:24:22 +0530952 vos_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Jeff Johnson295189b2012-06-20 16:38:30 -0700953 setKey.keyId = key_index; // Store Key ID
954 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
955 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
956 setKey.paeRole = 0 ; // the PAE role
957 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
958 {
959 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
960 }
961 else
962 {
963 isConnected = hdd_connIsConnected(pHddStaCtx);
964 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
965 }
966 setKey.keyLength = key_Len;
967 pKeyPtr = setKey.Key;
968 memcpy( pKeyPtr, key, key_Len);
969
970 hddLog(VOS_TRACE_LEVEL_INFO,"\n%s: WAPI KEY LENGTH:0x%04x",
971 __func__, key_Len);
972 for (n = 0 ; n < key_Len; n++)
973 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
974 __func__,n,setKey.Key[n]);
975
976 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
977 if ( isConnected )
978 {
979 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
980 pAdapter->sessionId, &setKey, &roamId );
981 }
982 if ( status != 0 )
983 {
984 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
985 "[%4d] sme_RoamSetKey returned ERROR status= %d",
986 __LINE__, status );
987 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
988 }
989}
990#endif /* FEATURE_WLAN_WAPI*/
991
992#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530993int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -0700994 beacon_data_t **ppBeacon,
995 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700996#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530997int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700998 beacon_data_t **ppBeacon,
999 struct cfg80211_beacon_data *params,
1000 int dtim_period)
1001#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301002{
Jeff Johnson295189b2012-06-20 16:38:30 -07001003 int size;
1004 beacon_data_t *beacon = NULL;
1005 beacon_data_t *old = NULL;
1006 int head_len,tail_len;
1007
Jeff Johnsone7245742012-09-05 17:12:55 -07001008 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07001009 if (params->head && !params->head_len)
1010 return -EINVAL;
1011
1012 old = pAdapter->sessionCtx.ap.beacon;
1013
1014 if (!params->head && !old)
1015 return -EINVAL;
1016
1017 if (params->tail && !params->tail_len)
1018 return -EINVAL;
1019
1020#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
1021 /* Kernel 3.0 is not updating dtim_period for set beacon */
1022 if (!params->dtim_period)
1023 return -EINVAL;
1024#endif
1025
1026 if(params->head)
1027 head_len = params->head_len;
1028 else
1029 head_len = old->head_len;
1030
1031 if(params->tail || !old)
1032 tail_len = params->tail_len;
1033 else
1034 tail_len = old->tail_len;
1035
1036 size = sizeof(beacon_data_t) + head_len + tail_len;
1037
1038 beacon = kzalloc(size, GFP_KERNEL);
1039
1040 if( beacon == NULL )
1041 return -ENOMEM;
1042
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001043#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001044 if(params->dtim_period || !old )
1045 beacon->dtim_period = params->dtim_period;
1046 else
1047 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001048#else
1049 if(dtim_period || !old )
1050 beacon->dtim_period = dtim_period;
1051 else
1052 beacon->dtim_period = old->dtim_period;
1053#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301054
Jeff Johnson295189b2012-06-20 16:38:30 -07001055 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
1056 beacon->tail = beacon->head + head_len;
1057 beacon->head_len = head_len;
1058 beacon->tail_len = tail_len;
1059
1060 if(params->head) {
1061 memcpy (beacon->head,params->head,beacon->head_len);
1062 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301063 else {
Jeff Johnson295189b2012-06-20 16:38:30 -07001064 if(old)
1065 memcpy (beacon->head,old->head,beacon->head_len);
1066 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301067
Jeff Johnson295189b2012-06-20 16:38:30 -07001068 if(params->tail) {
1069 memcpy (beacon->tail,params->tail,beacon->tail_len);
1070 }
1071 else {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301072 if(old)
Jeff Johnson295189b2012-06-20 16:38:30 -07001073 memcpy (beacon->tail,old->tail,beacon->tail_len);
1074 }
1075
1076 *ppBeacon = beacon;
1077
1078 kfree(old);
1079
1080 return 0;
1081
1082}
Jeff Johnson295189b2012-06-20 16:38:30 -07001083
1084v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
1085{
1086 int left = length;
1087 v_U8_t *ptr = pIes;
1088 v_U8_t elem_id,elem_len;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301089
Jeff Johnson295189b2012-06-20 16:38:30 -07001090 while(left >= 2)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301091 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001092 elem_id = ptr[0];
1093 elem_len = ptr[1];
1094 left -= 2;
1095 if(elem_len > left)
1096 {
1097 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001098 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -07001099 eid,elem_len,left);
1100 return NULL;
1101 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301102 if (elem_id == eid)
Jeff Johnson295189b2012-06-20 16:38:30 -07001103 {
1104 return ptr;
1105 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301106
Jeff Johnson295189b2012-06-20 16:38:30 -07001107 left -= elem_len;
1108 ptr += (elem_len + 2);
1109 }
1110 return NULL;
1111}
1112
Jeff Johnson295189b2012-06-20 16:38:30 -07001113/* Check if rate is 11g rate or not */
1114static int wlan_hdd_rate_is_11g(u8 rate)
1115{
Sanjay Devnani28322e22013-06-21 16:13:40 -07001116 static const u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 108}; /* actual rate * 2 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001117 u8 i;
1118 for (i = 0; i < 8; i++)
1119 {
1120 if(rate == gRateArray[i])
1121 return TRUE;
1122 }
1123 return FALSE;
1124}
1125
1126/* Check for 11g rate and set proper 11g only mode */
1127static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
1128 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
1129{
1130 u8 i, num_rates = pIe[0];
1131
1132 pIe += 1;
1133 for ( i = 0; i < num_rates; i++)
1134 {
1135 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
1136 {
1137 /* If rate set have 11g rate than change the mode to 11G */
1138 *pSapHw_mode = eSAP_DOT11_MODE_11g;
1139 if (pIe[i] & BASIC_RATE_MASK)
1140 {
1141 /* If we have 11g rate as basic rate, it means mode
1142 is 11g only mode.
1143 */
1144 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
1145 *pCheckRatesfor11g = FALSE;
1146 }
1147 }
1148 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
1149 {
1150 *require_ht = TRUE;
1151 }
1152 }
1153 return;
1154}
1155
1156static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
1157{
1158 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1159 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1160 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1161 u8 checkRatesfor11g = TRUE;
1162 u8 require_ht = FALSE;
1163 u8 *pIe=NULL;
1164
1165 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
1166
1167 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
1168 pBeacon->head_len, WLAN_EID_SUPP_RATES);
1169 if (pIe != NULL)
1170 {
1171 pIe += 1;
1172 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1173 &pConfig->SapHw_mode);
1174 }
1175
1176 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1177 WLAN_EID_EXT_SUPP_RATES);
1178 if (pIe != NULL)
1179 {
1180
1181 pIe += 1;
1182 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1183 &pConfig->SapHw_mode);
1184 }
1185
1186 if( pConfig->channel > 14 )
1187 {
1188 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
1189 }
1190
1191 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1192 WLAN_EID_HT_CAPABILITY);
1193
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301194 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001195 {
1196 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
1197 if(require_ht)
1198 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
1199 }
1200}
1201
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301202static int wlan_hdd_add_ie(hdd_adapter_t* pHostapdAdapter, v_U8_t *genie,
1203 v_U8_t *total_ielen, v_U8_t *oui, v_U8_t oui_size)
1204{
Arif Hussaine7f3ea52013-09-12 21:56:36 -07001205 v_U16_t ielen = 0;
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301206 v_U8_t *pIe = NULL;
1207 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1208
1209 pIe = wlan_hdd_get_vendor_oui_ie_ptr(oui, oui_size,
1210 pBeacon->tail, pBeacon->tail_len);
1211
1212 if (pIe)
1213 {
1214 ielen = pIe[1] + 2;
1215 if ((*total_ielen + ielen) <= MAX_GENIE_LEN)
1216 {
1217 vos_mem_copy(&genie[*total_ielen], pIe, ielen);
1218 }
1219 else
1220 {
1221 hddLog( VOS_TRACE_LEVEL_ERROR, "**Ie Length is too big***");
1222 return -EINVAL;
1223 }
1224 *total_ielen += ielen;
1225 }
1226 return 0;
1227}
1228
Arif Hussaine7f3ea52013-09-12 21:56:36 -07001229static void wlan_hdd_add_hostapd_conf_vsie(hdd_adapter_t* pHostapdAdapter,
1230 v_U8_t *genie, v_U8_t *total_ielen)
1231{
1232 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1233 int left = pBeacon->tail_len;
1234 v_U8_t *ptr = pBeacon->tail;
1235 v_U8_t elem_id, elem_len;
1236 v_U16_t ielen = 0;
1237
1238 if ( NULL == ptr || 0 == left )
1239 return;
1240
1241 while (left >= 2)
1242 {
1243 elem_id = ptr[0];
1244 elem_len = ptr[1];
1245 left -= 2;
1246 if (elem_len > left)
1247 {
1248 hddLog( VOS_TRACE_LEVEL_ERROR,
1249 "****Invalid IEs eid = %d elem_len=%d left=%d*****",
1250 elem_id, elem_len, left);
1251 return;
1252 }
1253 if (IE_EID_VENDOR == elem_id)
1254 {
1255 /* skipping the VSIE's which we don't want to include or
1256 * it will be included by existing code
1257 */
1258 if ((memcmp( &ptr[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) != 0 ) &&
1259#ifdef WLAN_FEATURE_WFD
1260 (memcmp( &ptr[2], WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE) != 0) &&
1261#endif
1262 (memcmp( &ptr[2], WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) &&
1263 (memcmp( &ptr[2], BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) &&
1264 (memcmp( &ptr[2], "\x00\x50\xf2\x02", WPA_OUI_TYPE_SIZE) != 0) &&
1265 (memcmp( &ptr[2], WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) &&
1266 (memcmp( &ptr[2], P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE) != 0))
1267 {
1268 ielen = ptr[1] + 2;
1269 if ((*total_ielen + ielen) <= MAX_GENIE_LEN)
1270 {
1271 vos_mem_copy(&genie[*total_ielen], ptr, ielen);
1272 *total_ielen += ielen;
1273 }
1274 else
1275 {
1276 hddLog( VOS_TRACE_LEVEL_ERROR,
1277 "IE Length is too big "
1278 "IEs eid=%d elem_len=%d total_ie_lent=%d",
1279 elem_id, elem_len, *total_ielen);
1280 }
1281 }
1282 }
1283
1284 left -= elem_len;
1285 ptr += (elem_len + 2);
1286 }
1287 return;
1288}
1289
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001290#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001291static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1292 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001293#else
1294static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1295 struct cfg80211_beacon_data *params)
1296#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001297{
1298 v_U8_t *genie;
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301299 v_U8_t total_ielen = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001300 v_U8_t addIE[1] = {0};
Jeff Johnsone7245742012-09-05 17:12:55 -07001301 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001302
1303 genie = vos_mem_malloc(MAX_GENIE_LEN);
1304
1305 if(genie == NULL) {
1306
1307 return -ENOMEM;
1308 }
1309
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301310 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1311 &total_ielen, WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001312 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301313 ret = -EINVAL;
1314 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001315 }
1316
1317#ifdef WLAN_FEATURE_WFD
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301318 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1319 &total_ielen, WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE))
1320 {
1321 ret = -EINVAL;
1322 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001323 }
1324#endif
1325
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301326 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1327 &total_ielen, P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001328 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301329 ret = -EINVAL;
1330 goto done;
1331 }
1332
1333 if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode)
1334 {
Arif Hussaine7f3ea52013-09-12 21:56:36 -07001335 wlan_hdd_add_hostapd_conf_vsie(pHostapdAdapter, genie, &total_ielen);
Jeff Johnson295189b2012-06-20 16:38:30 -07001336 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001337
1338 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1339 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1340 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1341 {
1342 hddLog(LOGE,
1343 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001344 ret = -EINVAL;
1345 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001346 }
1347
1348 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1349 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1350 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1351 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1352 ==eHAL_STATUS_FAILURE)
1353 {
1354 hddLog(LOGE,
1355 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001356 ret = -EINVAL;
1357 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001358 }
1359
1360 // Added for ProResp IE
1361 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1362 {
1363 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1364 u8 probe_rsp_ie_len[3] = {0};
1365 u8 counter = 0;
1366 /* Check Probe Resp Length if it is greater then 255 then Store
1367 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1368 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1369 Store More then 255 bytes into One Variable.
1370 */
1371 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1372 {
1373 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1374 {
1375 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1376 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1377 }
1378 else
1379 {
1380 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1381 rem_probe_resp_ie_len = 0;
1382 }
1383 }
1384
1385 rem_probe_resp_ie_len = 0;
1386
1387 if (probe_rsp_ie_len[0] > 0)
1388 {
1389 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1390 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1391 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1392 probe_rsp_ie_len[0], NULL,
1393 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1394 {
1395 hddLog(LOGE,
1396 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001397 ret = -EINVAL;
1398 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001399 }
1400 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1401 }
1402
1403 if (probe_rsp_ie_len[1] > 0)
1404 {
1405 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1406 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1407 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1408 probe_rsp_ie_len[1], NULL,
1409 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1410 {
1411 hddLog(LOGE,
1412 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001413 ret = -EINVAL;
1414 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001415 }
1416 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1417 }
1418
1419 if (probe_rsp_ie_len[2] > 0)
1420 {
1421 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1422 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1423 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1424 probe_rsp_ie_len[2], NULL,
1425 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1426 {
1427 hddLog(LOGE,
1428 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001429 ret = -EINVAL;
1430 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001431 }
1432 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1433 }
1434
1435 if (probe_rsp_ie_len[1] == 0 )
1436 {
1437 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1438 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1439 eANI_BOOLEAN_FALSE) )
1440 {
1441 hddLog(LOGE,
1442 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1443 }
1444 }
1445
1446 if (probe_rsp_ie_len[2] == 0 )
1447 {
1448 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1449 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1450 eANI_BOOLEAN_FALSE) )
1451 {
1452 hddLog(LOGE,
1453 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1454 }
1455 }
1456
1457 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1458 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1459 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1460 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1461 == eHAL_STATUS_FAILURE)
1462 {
1463 hddLog(LOGE,
1464 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001465 ret = -EINVAL;
1466 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001467 }
1468 }
1469 else
1470 {
1471 // Reset WNI_CFG_PROBE_RSP Flags
1472 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1473
1474 hddLog(VOS_TRACE_LEVEL_INFO,
1475 "%s: No Probe Response IE received in set beacon",
1476 __func__);
1477 }
1478
1479 // Added for AssocResp IE
1480 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1481 {
1482 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1483 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1484 params->assocresp_ies_len, NULL,
1485 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1486 {
1487 hddLog(LOGE,
1488 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001489 ret = -EINVAL;
1490 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001491 }
1492
1493 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1494 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1495 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1496 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1497 == eHAL_STATUS_FAILURE)
1498 {
1499 hddLog(LOGE,
1500 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001501 ret = -EINVAL;
1502 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001503 }
1504 }
1505 else
1506 {
1507 hddLog(VOS_TRACE_LEVEL_INFO,
1508 "%s: No Assoc Response IE received in set beacon",
1509 __func__);
1510
1511 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1512 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1513 eANI_BOOLEAN_FALSE) )
1514 {
1515 hddLog(LOGE,
1516 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1517 }
1518 }
1519
Jeff Johnsone7245742012-09-05 17:12:55 -07001520done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001521 vos_mem_free(genie);
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301522 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07001523}
Jeff Johnson295189b2012-06-20 16:38:30 -07001524
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301525/*
Jeff Johnson295189b2012-06-20 16:38:30 -07001526 * FUNCTION: wlan_hdd_validate_operation_channel
1527 * called by wlan_hdd_cfg80211_start_bss() and
1528 * wlan_hdd_cfg80211_set_channel()
1529 * This function validates whether given channel is part of valid
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301530 * channel list.
1531 */
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001532VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001533{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301534
Jeff Johnson295189b2012-06-20 16:38:30 -07001535 v_U32_t num_ch = 0;
1536 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1537 u32 indx = 0;
1538 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301539 v_U8_t fValidChannel = FALSE, count = 0;
1540 hdd_config_t *hdd_pConfig_ini= (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301541
Jeff Johnson295189b2012-06-20 16:38:30 -07001542 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1543
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301544 if ( hdd_pConfig_ini->sapAllowAllChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001545 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301546 /* Validate the channel */
1547 for (count = RF_CHAN_1 ; count <= RF_CHAN_165 ; count++)
Jeff Johnson295189b2012-06-20 16:38:30 -07001548 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301549 if ( channel == rfChannels[count].channelNum )
1550 {
1551 fValidChannel = TRUE;
1552 break;
1553 }
1554 }
1555 if (fValidChannel != TRUE)
1556 {
1557 hddLog(VOS_TRACE_LEVEL_ERROR,
1558 "%s: Invalid Channel [%d]", __func__, channel);
1559 return VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001560 }
1561 }
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301562 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001563 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301564 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1565 valid_ch, &num_ch))
1566 {
1567 hddLog(VOS_TRACE_LEVEL_ERROR,
1568 "%s: failed to get valid channel list", __func__);
1569 return VOS_STATUS_E_FAILURE;
1570 }
1571 for (indx = 0; indx < num_ch; indx++)
1572 {
1573 if (channel == valid_ch[indx])
1574 {
1575 break;
1576 }
1577 }
1578
1579 if (indx >= num_ch)
1580 {
1581 hddLog(VOS_TRACE_LEVEL_ERROR,
1582 "%s: Invalid Channel [%d]", __func__, channel);
1583 return VOS_STATUS_E_FAILURE;
1584 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001585 }
1586 return VOS_STATUS_SUCCESS;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301587
Jeff Johnson295189b2012-06-20 16:38:30 -07001588}
1589
Viral Modi3a32cc52013-02-08 11:14:52 -08001590/**
1591 * FUNCTION: wlan_hdd_cfg80211_set_channel
1592 * This function is used to set the channel number
1593 */
1594static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
1595 struct ieee80211_channel *chan,
1596 enum nl80211_channel_type channel_type
1597 )
1598{
1599 v_U32_t num_ch = 0;
Jeff Johnson4416a782013-03-25 14:17:50 -07001600 int channel = 0;
Viral Modi3a32cc52013-02-08 11:14:52 -08001601 hdd_adapter_t *pAdapter = NULL;
1602 int freq = chan->center_freq; /* freq is in MHZ */
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301603 hdd_context_t *pHddCtx;
1604 int status;
Viral Modi3a32cc52013-02-08 11:14:52 -08001605
1606 ENTER();
1607
1608 if( NULL == dev )
1609 {
1610 hddLog(VOS_TRACE_LEVEL_ERROR,
1611 "%s: Called with dev = NULL.\n", __func__);
1612 return -ENODEV;
1613 }
1614 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1615
1616 hddLog(VOS_TRACE_LEVEL_INFO,
1617 "%s: device_mode = %d freq = %d \n",__func__,
1618 pAdapter->device_mode, chan->center_freq);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301619
1620 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1621 status = wlan_hdd_validate_context(pHddCtx);
1622
1623 if (0 != status)
Viral Modi3a32cc52013-02-08 11:14:52 -08001624 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301625 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1626 "%s: HDD context is not valid", __func__);
1627 return status;
Viral Modi3a32cc52013-02-08 11:14:52 -08001628 }
1629
1630 /*
1631 * Do freq to chan conversion
1632 * TODO: for 11a
1633 */
1634
1635 channel = ieee80211_frequency_to_channel(freq);
1636
1637 /* Check freq range */
1638 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
1639 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
1640 {
1641 hddLog(VOS_TRACE_LEVEL_ERROR,
1642 "%s: Channel [%d] is outside valid range from %d to %d\n",
1643 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
1644 WNI_CFG_CURRENT_CHANNEL_STAMAX);
1645 return -EINVAL;
1646 }
1647
1648 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1649
Gopichand Nakkala6ab19562013-03-07 13:59:42 +05301650 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode) &&
1651 (WLAN_HDD_P2P_GO != pAdapter->device_mode))
Viral Modi3a32cc52013-02-08 11:14:52 -08001652 {
1653 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
1654 {
1655 hddLog(VOS_TRACE_LEVEL_ERROR,
1656 "%s: Invalid Channel [%d] \n", __func__, channel);
1657 return -EINVAL;
1658 }
1659 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1660 "%s: set channel to [%d] for device mode =%d",
1661 __func__, channel,pAdapter->device_mode);
1662 }
1663 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Viral Modi3a32cc52013-02-08 11:14:52 -08001664 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Viral Modi3a32cc52013-02-08 11:14:52 -08001665 )
1666 {
1667 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
1668 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
1669 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1670
1671 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
1672 {
1673 /* Link is up then return cant set channel*/
1674 hddLog( VOS_TRACE_LEVEL_ERROR,
1675 "%s: IBSS Associated, can't set the channel\n", __func__);
1676 return -EINVAL;
1677 }
1678
1679 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
1680 pHddStaCtx->conn_info.operationChannel = channel;
1681 pRoamProfile->ChannelInfo.ChannelList =
1682 &pHddStaCtx->conn_info.operationChannel;
1683 }
1684 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Viral Modi3a32cc52013-02-08 11:14:52 -08001685 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Viral Modi3a32cc52013-02-08 11:14:52 -08001686 )
1687 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301688 if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
1689 {
1690 if(VOS_STATUS_SUCCESS !=
1691 wlan_hdd_validate_operation_channel(pAdapter,channel))
1692 {
1693 hddLog(VOS_TRACE_LEVEL_ERROR,
1694 "%s: Invalid Channel [%d] \n", __func__, channel);
1695 return -EINVAL;
1696 }
1697 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1698 }
1699 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
Viral Modi3a32cc52013-02-08 11:14:52 -08001700 {
1701 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
1702
1703 /* If auto channel selection is configured as enable/ 1 then ignore
1704 channel set by supplicant
1705 */
1706 if ( cfg_param->apAutoChannelSelection )
1707 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301708 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel =
1709 AUTO_CHANNEL_SELECT;
Viral Modi3a32cc52013-02-08 11:14:52 -08001710 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1711 "%s: set channel to auto channel (0) for device mode =%d",
1712 __func__, pAdapter->device_mode);
1713 }
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301714 else
1715 {
1716 if(VOS_STATUS_SUCCESS !=
1717 wlan_hdd_validate_operation_channel(pAdapter,channel))
1718 {
1719 hddLog(VOS_TRACE_LEVEL_ERROR,
1720 "%s: Invalid Channel [%d] \n", __func__, channel);
1721 return -EINVAL;
1722 }
1723 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1724 }
Viral Modi3a32cc52013-02-08 11:14:52 -08001725 }
1726 }
1727 else
1728 {
1729 hddLog(VOS_TRACE_LEVEL_FATAL,
1730 "%s: Invalid device mode failed to set valid channel", __func__);
1731 return -EINVAL;
1732 }
1733 EXIT();
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301734 return status;
Viral Modi3a32cc52013-02-08 11:14:52 -08001735}
1736
Jeff Johnson295189b2012-06-20 16:38:30 -07001737#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1738static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1739 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001740#else
1741static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1742 struct cfg80211_beacon_data *params,
1743 const u8 *ssid, size_t ssid_len,
1744 enum nl80211_hidden_ssid hidden_ssid)
1745#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001746{
1747 tsap_Config_t *pConfig;
1748 beacon_data_t *pBeacon = NULL;
1749 struct ieee80211_mgmt *pMgmt_frame;
1750 v_U8_t *pIe=NULL;
1751 v_U16_t capab_info;
1752 eCsrAuthType RSNAuthType;
1753 eCsrEncryptionType RSNEncryptType;
1754 eCsrEncryptionType mcRSNEncryptType;
1755 int status = VOS_STATUS_SUCCESS;
1756 tpWLAN_SAPEventCB pSapEventCallback;
1757 hdd_hostapd_state_t *pHostapdState;
1758 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1759 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301760 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001761 struct qc_mac_acl_entry *acl_entry = NULL;
1762 v_SINT_t i;
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001763 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001764
1765 ENTER();
1766
1767 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1768
1769 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1770
1771 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1772
1773 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1774
1775 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1776
1777 //channel is already set in the set_channel Call back
1778 //pConfig->channel = pCommitConfig->channel;
1779
1780 /*Protection parameter to enable or disable*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301781 pConfig->protEnabled =
Jeff Johnson295189b2012-06-20 16:38:30 -07001782 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1783
1784 pConfig->dtim_period = pBeacon->dtim_period;
1785
1786 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1787 pConfig->dtim_period);
1788
1789
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001790 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001791 {
1792 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001793 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001794 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001795 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001796 tANI_BOOLEAN restartNeeded;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001797 pConfig->ieee80211d = 1;
1798 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1799 sme_setRegInfo(hHal, pConfig->countryCode);
1800 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
Jeff Johnson295189b2012-06-20 16:38:30 -07001801 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001802 else
1803 {
1804 pConfig->ieee80211d = 0;
1805 }
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301806 /*
1807 * If auto channel is configured i.e. channel is 0,
1808 * so skip channel validation.
1809 */
1810 if( AUTO_CHANNEL_SELECT != pConfig->channel )
1811 {
1812 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1813 {
1814 hddLog(VOS_TRACE_LEVEL_ERROR,
1815 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1816 return -EINVAL;
1817 }
1818 }
1819 else
1820 {
1821 if(1 != pHddCtx->is_dynamic_channel_range_set)
1822 {
1823 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
1824 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
1825 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
1826 }
1827 pHddCtx->is_dynamic_channel_range_set = 0;
1828 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001829 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001830 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001831 {
1832 pConfig->ieee80211d = 0;
1833 }
1834 pConfig->authType = eSAP_AUTO_SWITCH;
1835
1836 capab_info = pMgmt_frame->u.beacon.capab_info;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301837
1838 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
Jeff Johnson295189b2012-06-20 16:38:30 -07001839 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1840
1841 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1842
1843 /*Set wps station to configured*/
1844 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1845
1846 if(pIe)
1847 {
1848 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1849 {
1850 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1851 return -EINVAL;
1852 }
1853 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1854 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001855 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001856 /* Check 15 bit of WPS IE as it contain information for wps state
1857 * WPS state
1858 */
1859 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1860 {
1861 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1862 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1863 {
1864 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1865 }
1866 }
1867 }
1868 else
1869 {
1870 pConfig->wps_state = SAP_WPS_DISABLED;
1871 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301872 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
Jeff Johnson295189b2012-06-20 16:38:30 -07001873
1874 pConfig->RSNWPAReqIELength = 0;
1875 pConfig->pRSNWPAReqIE = NULL;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301876 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001877 WLAN_EID_RSN);
1878 if(pIe && pIe[1])
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301879 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001880 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1881 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1882 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301883 /* The actual processing may eventually be more extensive than
1884 * this. Right now, just consume any PMKIDs that are sent in
Jeff Johnson295189b2012-06-20 16:38:30 -07001885 * by the app.
1886 * */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301887 status = hdd_softap_unpackIE(
Jeff Johnson295189b2012-06-20 16:38:30 -07001888 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1889 &RSNEncryptType,
1890 &mcRSNEncryptType,
1891 &RSNAuthType,
1892 pConfig->pRSNWPAReqIE[1]+2,
1893 pConfig->pRSNWPAReqIE );
1894
1895 if( VOS_STATUS_SUCCESS == status )
1896 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301897 /* Now copy over all the security attributes you have
1898 * parsed out
Jeff Johnson295189b2012-06-20 16:38:30 -07001899 * */
1900 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1901 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1902 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1903 = RSNEncryptType;
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05301904 hddLog( LOG1, FL("CSR AuthType = %d, "
Jeff Johnson295189b2012-06-20 16:38:30 -07001905 "EncryptionType = %d mcEncryptionType = %d\n"),
1906 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1907 }
1908 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301909
Jeff Johnson295189b2012-06-20 16:38:30 -07001910 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1911 pBeacon->tail, pBeacon->tail_len);
1912
1913 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1914 {
1915 if (pConfig->pRSNWPAReqIE)
1916 {
1917 /*Mixed mode WPA/WPA2*/
1918 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1919 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1920 }
1921 else
1922 {
1923 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1924 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1925 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301926 status = hdd_softap_unpackIE(
Jeff Johnson295189b2012-06-20 16:38:30 -07001927 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1928 &RSNEncryptType,
1929 &mcRSNEncryptType,
1930 &RSNAuthType,
1931 pConfig->pRSNWPAReqIE[1]+2,
1932 pConfig->pRSNWPAReqIE );
1933
1934 if( VOS_STATUS_SUCCESS == status )
1935 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301936 /* Now copy over all the security attributes you have
1937 * parsed out
Jeff Johnson295189b2012-06-20 16:38:30 -07001938 * */
1939 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1940 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1941 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1942 = RSNEncryptType;
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05301943 hddLog( LOG1, FL("CSR AuthType = %d, "
Jeff Johnson295189b2012-06-20 16:38:30 -07001944 "EncryptionType = %d mcEncryptionType = %d\n"),
1945 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1946 }
1947 }
1948 }
1949
Jeff Johnson4416a782013-03-25 14:17:50 -07001950 if (pConfig->RSNWPAReqIELength > sizeof wpaRsnIEdata) {
1951 hddLog( VOS_TRACE_LEVEL_ERROR, "**RSNWPAReqIELength is too large***");
1952 return -EINVAL;
1953 }
1954
Jeff Johnson295189b2012-06-20 16:38:30 -07001955 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1956
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001957#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001958 if (params->ssid != NULL)
1959 {
1960 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1961 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1962 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1963 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1964 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001965#else
1966 if (ssid != NULL)
1967 {
1968 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1969 pConfig->SSIDinfo.ssid.length = ssid_len;
1970 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1971 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1972 }
1973#endif
1974
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301975 vos_mem_copy(pConfig->self_macaddr.bytes,
Jeff Johnson295189b2012-06-20 16:38:30 -07001976 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301977
Jeff Johnson295189b2012-06-20 16:38:30 -07001978 /* default value */
1979 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1980 pConfig->num_accept_mac = 0;
1981 pConfig->num_deny_mac = 0;
1982
1983 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1984 pBeacon->tail, pBeacon->tail_len);
1985
1986 /* pIe for black list is following form:
1987 type : 1 byte
1988 length : 1 byte
1989 OUI : 4 bytes
1990 acl type : 1 byte
1991 no of mac addr in black list: 1 byte
1992 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301993 */
1994 if ((pIe != NULL) && (pIe[1] != 0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001995 {
1996 pConfig->SapMacaddr_acl = pIe[6];
1997 pConfig->num_deny_mac = pIe[7];
1998 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1999 pIe[6], pIe[7]);
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05302000 if (pConfig->num_deny_mac > MAX_ACL_MAC_ADDRESS)
2001 pConfig->num_deny_mac = MAX_ACL_MAC_ADDRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07002002 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
2003 for (i = 0; i < pConfig->num_deny_mac; i++)
2004 {
2005 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
2006 acl_entry++;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302007 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002008 }
2009 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
2010 pBeacon->tail, pBeacon->tail_len);
2011
2012 /* pIe for white list is following form:
2013 type : 1 byte
2014 length : 1 byte
2015 OUI : 4 bytes
2016 acl type : 1 byte
2017 no of mac addr in white list: 1 byte
2018 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302019 */
2020 if ((pIe != NULL) && (pIe[1] != 0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002021 {
2022 pConfig->SapMacaddr_acl = pIe[6];
2023 pConfig->num_accept_mac = pIe[7];
2024 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
2025 pIe[6], pIe[7]);
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05302026 if (pConfig->num_accept_mac > MAX_ACL_MAC_ADDRESS)
2027 pConfig->num_accept_mac = MAX_ACL_MAC_ADDRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07002028 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
2029 for (i = 0; i < pConfig->num_accept_mac; i++)
2030 {
2031 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
2032 acl_entry++;
2033 }
2034 }
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05302035
Jeff Johnson295189b2012-06-20 16:38:30 -07002036 wlan_hdd_set_sapHwmode(pHostapdAdapter);
2037
Jeff Johnsone7245742012-09-05 17:12:55 -07002038#ifdef WLAN_FEATURE_11AC
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08002039 /* Overwrite the hostapd setting for HW mode only for 11ac.
2040 * This is valid only if mode is set to 11n in hostapd and either AUTO or 11ac in .ini .
2041 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode) */
2042 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
2043 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302044 (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08002045 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
2046 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07002047 {
2048 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
Ravi Joshi83bfaa12013-05-28 22:12:08 -07002049
2050 /* Disable VHT support in 2.4 GHz band */
2051 if (pConfig->channel <= 14 &&
2052 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->enableVhtFor24GHzBand == FALSE)
2053 {
2054 pConfig->SapHw_mode = eSAP_DOT11_MODE_11n;
2055 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002056 }
2057#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302058
Ravi Joshiaeb7d9e2013-05-02 12:28:14 -07002059 if ( AUTO_CHANNEL_SELECT != pConfig->channel )
2060 {
2061 sme_SelectCBMode(hHal,
2062 sapConvertSapPhyModeToCsrPhyMode(pConfig->SapHw_mode),
2063 pConfig->channel);
2064 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002065 // ht_capab is not what the name conveys,this is used for protection bitmap
2066 pConfig->ht_capab =
2067 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
2068
2069 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
2070 {
2071 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
2072 return -EINVAL;
2073 }
2074
2075 //Uapsd Enabled Bit
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302076 pConfig->UapsdEnable =
Jeff Johnson295189b2012-06-20 16:38:30 -07002077 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
2078 //Enable OBSS protection
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302079 pConfig->obssProtEnabled =
2080 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
Jeff Johnson295189b2012-06-20 16:38:30 -07002081
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302082 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
Jeff Johnson295189b2012-06-20 16:38:30 -07002083 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302084 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
Jeff Johnson295189b2012-06-20 16:38:30 -07002085 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
2086 (int)pConfig->channel);
2087 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302088 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
2089 pConfig->authType);
Jeff Johnson295189b2012-06-20 16:38:30 -07002090 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302091 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
Jeff Johnson295189b2012-06-20 16:38:30 -07002092 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
2093 pConfig->protEnabled, pConfig->obssProtEnabled);
2094
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302095 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07002096 {
2097 //Bss already started. just return.
2098 //TODO Probably it should update some beacon params.
2099 hddLog( LOGE, "Bss Already started...Ignore the request");
2100 EXIT();
2101 return 0;
2102 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302103
Jeff Johnson295189b2012-06-20 16:38:30 -07002104 pConfig->persona = pHostapdAdapter->device_mode;
2105
2106 pSapEventCallback = hdd_hostapd_SAPEventCB;
2107 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
2108 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
2109 {
2110 hddLog(LOGE,FL("SAP Start Bss fail\n"));
2111 return -EINVAL;
2112 }
2113
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302114 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07002115 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
2116
2117 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302118
Jeff Johnson295189b2012-06-20 16:38:30 -07002119 if (!VOS_IS_STATUS_SUCCESS(status))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302120 {
2121 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07002122 ("ERROR: HDD vos wait for single_event failed!!\n"));
Tushnim Bhattacharyyaad37df12013-10-02 12:01:33 -07002123 smeGetCommandQStatus(hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07002124 VOS_ASSERT(0);
2125 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302126
Jeff Johnson295189b2012-06-20 16:38:30 -07002127 //Succesfully started Bss update the state bit.
2128 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
2129
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002130#ifdef WLAN_FEATURE_P2P_DEBUG
2131 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
2132 {
2133 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
2134 {
2135 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
2136 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002137 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002138 }
2139 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
2140 {
2141 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
2142 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002143 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002144 }
2145 }
2146#endif
2147
Jeff Johnson295189b2012-06-20 16:38:30 -07002148 pHostapdState->bCommit = TRUE;
2149 EXIT();
2150
2151 return 0;
2152}
2153
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002154#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302155static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
2156 struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -07002157 struct beacon_parameters *params)
2158{
2159 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302160 hdd_context_t *pHddCtx;
2161 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002162
2163 ENTER();
2164
2165 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
2166
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302167 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2168 status = wlan_hdd_validate_context(pHddCtx);
2169
2170 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002171 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302172 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2173 "%s: HDD context is not valid", __func__);
2174 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002175 }
2176
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302177 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002178 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002179 )
2180 {
2181 beacon_data_t *old,*new;
2182
2183 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302184
Jeff Johnson295189b2012-06-20 16:38:30 -07002185 if (old)
2186 return -EALREADY;
2187
2188 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2189
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302190 if(status != VOS_STATUS_SUCCESS)
Jeff Johnson295189b2012-06-20 16:38:30 -07002191 {
2192 hddLog(VOS_TRACE_LEVEL_FATAL,
2193 "%s:Error!!! Allocating the new beacon\n",__func__);
2194 return -EINVAL;
2195 }
2196
2197 pAdapter->sessionCtx.ap.beacon = new;
2198
2199 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2200 }
2201
2202 EXIT();
2203 return status;
2204}
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302205
2206static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07002207 struct net_device *dev,
2208 struct beacon_parameters *params)
2209{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302210 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302211 hdd_context_t *pHddCtx;
2212 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002213
2214 ENTER();
2215
2216 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2217 __func__,pAdapter->device_mode);
2218
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302219 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2220 status = wlan_hdd_validate_context(pHddCtx);
2221
2222 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002223 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302224 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2225 "%s: HDD context is not valid", __func__);
2226 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002227 }
2228
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302229 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002230 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302231 )
Jeff Johnson295189b2012-06-20 16:38:30 -07002232 {
2233 beacon_data_t *old,*new;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302234
Jeff Johnson295189b2012-06-20 16:38:30 -07002235 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302236
Jeff Johnson295189b2012-06-20 16:38:30 -07002237 if (!old)
2238 return -ENOENT;
2239
2240 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2241
2242 if(status != VOS_STATUS_SUCCESS) {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302243 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -07002244 "%s: Error!!! Allocating the new beacon\n",__func__);
2245 return -EINVAL;
2246 }
2247
2248 pAdapter->sessionCtx.ap.beacon = new;
2249
2250 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2251 }
2252
2253 EXIT();
2254 return status;
2255}
2256
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002257#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
2258
2259#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002260static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
2261 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002262#else
2263static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
2264 struct net_device *dev)
2265#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002266{
2267 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07002268 hdd_context_t *pHddCtx = NULL;
2269 hdd_scaninfo_t *pScanInfo = NULL;
2270 hdd_adapter_t *staAdapter = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302271 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002272
2273 ENTER();
2274
2275 if (NULL == pAdapter)
2276 {
2277 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002278 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002279 return -ENODEV;
2280 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002281
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302282 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2283 status = wlan_hdd_validate_context(pHddCtx);
2284
2285 if (0 != status)
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002286 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302287 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2288 "%s: HDD context is not valid", __func__);
2289 return status;
Jeff Johnson4416a782013-03-25 14:17:50 -07002290 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002291
2292 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
2293 if (NULL == staAdapter)
2294 {
2295 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
2296 if (NULL == staAdapter)
2297 {
Rajesh Chauhan52d885b2013-11-01 10:54:25 -07002298 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2299 "%s: HDD adapter context for STA/P2P-CLI is Null",
2300 __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002301 }
2302 }
2303
2304 pScanInfo = &pHddCtx->scan_info;
2305
Jeff Johnson295189b2012-06-20 16:38:30 -07002306 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2307 __func__,pAdapter->device_mode);
2308
Rajesh Chauhan52d885b2013-11-01 10:54:25 -07002309 if ((pScanInfo != NULL) && pScanInfo->mScanPending && staAdapter)
Jeff Johnsone7245742012-09-05 17:12:55 -07002310 {
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002311 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05302312 hdd_abort_mac_scan(staAdapter->pHddCtx, pAdapter->sessionId);
Jeff Johnsone7245742012-09-05 17:12:55 -07002313 status = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002314 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07002315 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
2316 if (!status)
2317 {
Rajesh Chauhan52d885b2013-11-01 10:54:25 -07002318 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -08002319 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002320 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07002321 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07002322 }
2323 }
2324
Jeff Johnson295189b2012-06-20 16:38:30 -07002325 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002326 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002327 )
2328 {
2329 beacon_data_t *old;
2330
2331 old = pAdapter->sessionCtx.ap.beacon;
2332
2333 if (!old)
2334 return -ENOENT;
2335
Jeff Johnson295189b2012-06-20 16:38:30 -07002336 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002337
2338 mutex_lock(&pHddCtx->sap_lock);
2339 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2340 {
Jeff Johnson4416a782013-03-25 14:17:50 -07002341 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss(pHddCtx->pvosContext) ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07002342 {
2343 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2344
2345 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2346
2347 if (!VOS_IS_STATUS_SUCCESS(status))
2348 {
2349 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2350 ("ERROR: HDD vos wait for single_event failed!!\n"));
2351 VOS_ASSERT(0);
2352 }
2353 }
2354 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2355 }
2356 mutex_unlock(&pHddCtx->sap_lock);
2357
2358 if(status != VOS_STATUS_SUCCESS)
2359 {
2360 hddLog(VOS_TRACE_LEVEL_FATAL,
2361 "%s:Error!!! Stopping the BSS\n",__func__);
2362 return -EINVAL;
2363 }
2364
Jeff Johnson4416a782013-03-25 14:17:50 -07002365 if (ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002366 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
2367 ==eHAL_STATUS_FAILURE)
2368 {
2369 hddLog(LOGE,
2370 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
2371 }
2372
Jeff Johnson4416a782013-03-25 14:17:50 -07002373 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002374 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2375 eANI_BOOLEAN_FALSE) )
2376 {
2377 hddLog(LOGE,
2378 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
2379 }
2380
2381 // Reset WNI_CFG_PROBE_RSP Flags
2382 wlan_hdd_reset_prob_rspies(pAdapter);
2383
2384 pAdapter->sessionCtx.ap.beacon = NULL;
2385 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002386#ifdef WLAN_FEATURE_P2P_DEBUG
2387 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
2388 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
2389 {
2390 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
2391 "GO got removed");
2392 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
2393 }
2394#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002395 }
2396 EXIT();
2397 return status;
2398}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002399
2400#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2401
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302402static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2403 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002404 struct cfg80211_ap_settings *params)
2405{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302406 hdd_adapter_t *pAdapter;
2407 hdd_context_t *pHddCtx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302408 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002409
2410 ENTER();
2411
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302412 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002413 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302414 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302415 "%s: Device is Null", __func__);
2416 return -ENODEV;
2417 }
2418
2419 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2420 if (NULL == pAdapter)
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 is Null", __func__);
2424 return -ENODEV;
2425 }
2426
2427 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2428 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302429 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302430 "%s: HDD adapter magic is invalid", __func__);
2431 return -ENODEV;
2432 }
2433
2434 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302435 status = wlan_hdd_validate_context(pHddCtx);
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302436
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302437 if (0 != status)
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302438 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302439 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2440 "%s: HDD context is not valid", __func__);
2441 return status;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302442 }
2443
2444 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2445 __func__, pAdapter->device_mode);
2446
2447 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002448 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002449 )
2450 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302451 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002452
2453 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302454
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002455 if (old)
2456 return -EALREADY;
2457
2458 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2459
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302460 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002461 {
2462 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302463 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002464 return -EINVAL;
2465 }
2466 pAdapter->sessionCtx.ap.beacon = new;
Viral Modi3a32cc52013-02-08 11:14:52 -08002467#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Yue Maf49ba872013-08-19 12:04:25 -07002468 wlan_hdd_cfg80211_set_channel(wiphy, dev,
2469#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2470 params->channel, params->channel_type);
2471#else
2472 params->chandef.chan, cfg80211_get_chandef_type(&(params->chandef)));
2473#endif
Viral Modi3a32cc52013-02-08 11:14:52 -08002474#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002475 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2476 params->ssid_len, params->hidden_ssid);
2477 }
2478
2479 EXIT();
2480 return status;
2481}
2482
2483
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302484static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002485 struct net_device *dev,
2486 struct cfg80211_beacon_data *params)
2487{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302488 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302489 hdd_context_t *pHddCtx;
2490 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002491
2492 ENTER();
2493
2494 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2495 __func__, pAdapter->device_mode);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302496
2497 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2498 status = wlan_hdd_validate_context(pHddCtx);
2499
2500 if (0 != status)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002501 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302502 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2503 "%s: HDD context is not valid", __func__);
2504 return status;
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002505 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002506
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302507 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002508 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302509 )
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002510 {
2511 beacon_data_t *old,*new;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302512
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002513 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302514
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002515 if (!old)
2516 return -ENOENT;
2517
2518 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2519
2520 if(status != VOS_STATUS_SUCCESS) {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302521 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002522 "%s: Error!!! Allocating the new beacon\n",__func__);
2523 return -EINVAL;
2524 }
2525
2526 pAdapter->sessionCtx.ap.beacon = new;
2527
2528 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2529 }
2530
2531 EXIT();
2532 return status;
2533}
2534
2535#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2536
Jeff Johnson295189b2012-06-20 16:38:30 -07002537
2538static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2539 struct net_device *dev,
2540 struct bss_parameters *params)
2541{
2542 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2543
2544 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302545
Jeff Johnson295189b2012-06-20 16:38:30 -07002546 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2547 __func__,pAdapter->device_mode);
2548
2549 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002550 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302551 )
Jeff Johnson295189b2012-06-20 16:38:30 -07002552 {
2553 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2554 * want to update this parameter */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302555 if (-1 != params->ap_isolate)
Jeff Johnson295189b2012-06-20 16:38:30 -07002556 {
2557 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302558 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002559 }
2560
2561 EXIT();
2562 return 0;
2563}
2564
Kiet Lam10841362013-11-01 11:36:50 +05302565/* FUNCTION: wlan_hdd_change_country_code_cd
2566* to wait for contry code completion
2567*/
2568void* wlan_hdd_change_country_code_cb(void *pAdapter)
2569{
2570 hdd_adapter_t *call_back_pAdapter = pAdapter;
2571 complete(&call_back_pAdapter->change_country_code);
2572 return NULL;
2573}
2574
Jeff Johnson295189b2012-06-20 16:38:30 -07002575/*
2576 * FUNCTION: wlan_hdd_cfg80211_change_iface
2577 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2578 */
2579int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2580 struct net_device *ndev,
2581 enum nl80211_iftype type,
2582 u32 *flags,
2583 struct vif_params *params
2584 )
2585{
2586 struct wireless_dev *wdev;
2587 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2588 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002589 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002590 tCsrRoamProfile *pRoamProfile = NULL;
2591 eCsrRoamBssType LastBSSType;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302592 hdd_config_t *pConfig = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002593 eMib_dot11DesiredBssType connectedBssType;
2594 VOS_STATUS status;
2595
2596 ENTER();
2597
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302598 status = wlan_hdd_validate_context(pHddCtx);
2599
2600 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07002601 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302602 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2603 "%s: HDD context is not valid", __func__);
2604 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002605 }
2606
2607 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2608 __func__, pAdapter->device_mode);
2609
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302610 pConfig = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07002611 wdev = ndev->ieee80211_ptr;
2612
2613#ifdef WLAN_BTAMP_FEATURE
2614 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2615 (NL80211_IFTYPE_ADHOC == type)||
2616 (NL80211_IFTYPE_AP == type)||
2617 (NL80211_IFTYPE_P2P_GO == type))
2618 {
2619 pHddCtx->isAmpAllowed = VOS_FALSE;
2620 // stop AMP traffic
2621 status = WLANBAP_StopAmp();
2622 if(VOS_STATUS_SUCCESS != status )
2623 {
2624 pHddCtx->isAmpAllowed = VOS_TRUE;
2625 hddLog(VOS_TRACE_LEVEL_FATAL,
2626 "%s: Failed to stop AMP", __func__);
2627 return -EINVAL;
2628 }
2629 }
2630#endif //WLAN_BTAMP_FEATURE
2631 /* Reset the current device mode bit mask*/
2632 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2633
2634 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07002635 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002636 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002637 )
2638 {
2639 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2640 pRoamProfile = &pWextState->roamProfile;
2641 LastBSSType = pRoamProfile->BSSType;
2642
2643 switch (type)
2644 {
2645 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002646 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002647 hddLog(VOS_TRACE_LEVEL_INFO,
2648 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2649 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002650#ifdef WLAN_FEATURE_11AC
2651 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2652 {
2653 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2654 }
2655#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302656 pRoamProfile->phyMode =
Jeff Johnsone7245742012-09-05 17:12:55 -07002657 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002658 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002659 //Check for sub-string p2p to confirm its a p2p interface
2660 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302661 {
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002662 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2663 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2664 }
2665 else
2666 {
2667 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002668 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002669 }
Madan Mohan Koyyalamudi81746922013-07-17 14:38:51 +05302670#ifdef FEATURE_WLAN_TDLS
2671 /* The open adapter for the p2p shall skip initializations in
2672 * tdls_init if the device mode is WLAN_HDD_P2P_DEVICE, for
2673 * TDLS is supported only on WLAN_HDD_P2P_CLIENT. Hence invoke
2674 * tdls_init when the change_iface sets the device mode to
2675 * WLAN_HDD_P2P_CLIENT.
2676 */
2677
2678 if ( pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2679 {
2680 if (0 != wlan_hdd_tdls_init (pAdapter))
2681 {
2682 return -EINVAL;
2683 }
2684 }
2685#endif
2686
Jeff Johnson295189b2012-06-20 16:38:30 -07002687 break;
2688 case NL80211_IFTYPE_ADHOC:
2689 hddLog(VOS_TRACE_LEVEL_INFO,
2690 "%s: setting interface Type to ADHOC", __func__);
2691 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2692 pRoamProfile->phyMode =
2693 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Shailender Karmuchia734f332013-04-19 14:02:48 -07002694 pAdapter->device_mode = WLAN_HDD_IBSS;
Jeff Johnson295189b2012-06-20 16:38:30 -07002695 wdev->iftype = type;
2696 break;
2697
2698 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002699 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002700 {
2701 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2702 "%s: setting interface Type to %s", __func__,
2703 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2704
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002705 //Cancel any remain on channel for GO mode
2706 if (NL80211_IFTYPE_P2P_GO == type)
2707 {
2708 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2709 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002710 if (NL80211_IFTYPE_AP == type)
2711 {
2712 /* As Loading WLAN Driver one interface being created for p2p device
2713 * address. This will take one HW STA and the max number of clients
2714 * that can connect to softAP will be reduced by one. so while changing
2715 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2716 * interface as it is not required in SoftAP mode.
2717 */
2718
2719 // Get P2P Adapter
2720 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2721
2722 if (pP2pAdapter)
2723 {
2724 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2725 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2726 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2727 }
2728 }
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05302729#ifdef FEATURE_WLAN_TDLS
Mohit Khanna0f232092012-09-11 14:46:08 -07002730
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05302731 /* A Mutex Lock is introduced while changing the mode to
2732 * protect the concurrent access for the Adapters by TDLS
2733 * module.
2734 */
2735 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
2736 {
2737 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2738 "%s: unable to lock list", __func__);
2739 return -EINVAL;
2740 }
2741#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002742 //De-init the adapter.
2743 hdd_stop_adapter( pHddCtx, pAdapter );
2744 hdd_deinit_adapter( pHddCtx, pAdapter );
2745 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
Jeff Johnson295189b2012-06-20 16:38:30 -07002746 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2747 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05302748#ifdef FEATURE_WLAN_TDLS
2749 mutex_unlock(&pHddCtx->tdls_lock);
2750#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07002751
2752 //Disable BMPS and IMPS if enabled
2753 //before starting Go
2754 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2755 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302756 if(VOS_STATUS_E_FAILURE ==
Jeff Johnson32d95a32012-09-10 13:15:23 -07002757 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2758 {
2759 //Fail to Exit BMPS
2760 VOS_ASSERT(0);
2761 }
2762 }
2763
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002764 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2765 (pConfig->apRandomBssidEnabled))
2766 {
2767 /* To meet Android requirements create a randomized
2768 MAC address of the form 02:1A:11:Fx:xx:xx */
2769 get_random_bytes(&ndev->dev_addr[3], 3);
2770 ndev->dev_addr[0] = 0x02;
2771 ndev->dev_addr[1] = 0x1A;
2772 ndev->dev_addr[2] = 0x11;
2773 ndev->dev_addr[3] |= 0xF0;
2774 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2775 VOS_MAC_ADDR_SIZE);
2776 pr_info("wlan: Generated HotSpot BSSID "
2777 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2778 ndev->dev_addr[0],
2779 ndev->dev_addr[1],
2780 ndev->dev_addr[2],
2781 ndev->dev_addr[3],
2782 ndev->dev_addr[4],
2783 ndev->dev_addr[5]);
2784 }
2785
Jeff Johnson295189b2012-06-20 16:38:30 -07002786 hdd_set_ap_ops( pAdapter->dev );
2787
Kiet Lam10841362013-11-01 11:36:50 +05302788 /* This is for only SAP mode where users can
2789 * control country through ini.
2790 * P2P GO follows station country code
2791 * acquired during the STA scanning. */
2792 if((NL80211_IFTYPE_AP == type) &&
2793 (memcmp(pConfig->apCntryCode, CFG_AP_COUNTRY_CODE_DEFAULT, 3) != 0))
2794 {
2795 int status = 0;
2796 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_INFO,
2797 "%s: setting country code from INI ", __func__);
2798 init_completion(&pAdapter->change_country_code);
2799 status = (int)sme_ChangeCountryCode(pHddCtx->hHal,
2800 (void *)(tSmeChangeCountryCallback)
2801 wlan_hdd_change_country_code_cb,
2802 pConfig->apCntryCode, pAdapter,
2803 pHddCtx->pvosContext,
2804 VOS_FALSE);
2805 if (eHAL_STATUS_SUCCESS == status)
2806 {
2807 /* Wait for completion */
2808 status = wait_for_completion_interruptible_timeout(
2809 &pAdapter->change_country_code,
2810 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
2811 if (status <= 0)
2812 {
2813 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2814 "%s: SME Timed out while setting country code ",
2815 __func__);
2816 }
2817 }
2818 else
2819 {
2820 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2821 "%s: SME Change Country code failed \n",__func__);
2822 return -EINVAL;
2823 }
2824 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002825 status = hdd_init_ap_mode(pAdapter);
2826 if(status != VOS_STATUS_SUCCESS)
2827 {
2828 hddLog(VOS_TRACE_LEVEL_FATAL,
2829 "%s: Error initializing the ap mode", __func__);
2830 return -EINVAL;
2831 }
2832 hdd_set_conparam(1);
2833
Jeff Johnson295189b2012-06-20 16:38:30 -07002834 /*interface type changed update in wiphy structure*/
2835 if(wdev)
2836 {
2837 wdev->iftype = type;
2838 pHddCtx->change_iface = type;
2839 }
2840 else
2841 {
2842 hddLog(VOS_TRACE_LEVEL_ERROR,
2843 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2844 return -EINVAL;
2845 }
2846 goto done;
2847 }
2848
2849 default:
2850 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2851 __func__);
2852 return -EOPNOTSUPP;
2853 }
2854 }
2855 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002856 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002857 )
2858 {
2859 switch(type)
2860 {
2861 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002862 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002863 case NL80211_IFTYPE_ADHOC:
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05302864#ifdef FEATURE_WLAN_TDLS
2865
2866 /* A Mutex Lock is introduced while changing the mode to
2867 * protect the concurrent access for the Adapters by TDLS
2868 * module.
2869 */
2870 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
2871 {
2872 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2873 "%s: unable to lock list", __func__);
2874 return -EINVAL;
2875 }
2876#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07002877 hdd_stop_adapter( pHddCtx, pAdapter );
2878 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002879 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002880 //Check for sub-string p2p to confirm its a p2p interface
2881 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002882 {
2883 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2884 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2885 }
2886 else
2887 {
2888 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002889 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002890 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002891 hdd_set_conparam(0);
2892 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002893 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2894 hdd_set_station_ops( pAdapter->dev );
2895 status = hdd_init_station_mode( pAdapter );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05302896#ifdef FEATURE_WLAN_TDLS
2897 mutex_unlock(&pHddCtx->tdls_lock);
2898#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002899 if( VOS_STATUS_SUCCESS != status )
2900 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002901 /* In case of JB, for P2P-GO, only change interface will be called,
2902 * This is the right place to enable back bmps_imps()
2903 */
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05302904 if (pHddCtx->hdd_wlan_suspended)
2905 {
2906 hdd_set_pwrparams(pHddCtx);
2907 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002908 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002909 goto done;
2910 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002911 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002912 wdev->iftype = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002913 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2914 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07002915 goto done;
2916 default:
2917 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2918 __func__);
2919 return -EOPNOTSUPP;
2920
2921 }
2922
2923 }
2924 else
2925 {
2926 return -EOPNOTSUPP;
2927 }
2928
2929
2930 if(pRoamProfile)
2931 {
2932 if ( LastBSSType != pRoamProfile->BSSType )
2933 {
2934 /*interface type changed update in wiphy structure*/
2935 wdev->iftype = type;
2936
2937 /*the BSS mode changed, We need to issue disconnect
2938 if connected or in IBSS disconnect state*/
2939 if ( hdd_connGetConnectedBssType(
2940 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2941 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2942 {
2943 /*need to issue a disconnect to CSR.*/
2944 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2945 if( eHAL_STATUS_SUCCESS ==
2946 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2947 pAdapter->sessionId,
2948 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2949 {
2950 wait_for_completion_interruptible_timeout(
2951 &pAdapter->disconnect_comp_var,
2952 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2953 }
2954 }
2955 }
2956 }
2957
2958done:
2959 /*set bitmask based on updated value*/
2960 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
Leo Chang6fe1f922013-06-07 19:21:24 -07002961
2962 /* Only STA mode support TM now
2963 * all other mode, TM feature should be disabled */
2964 if ( (pHddCtx->cfg_ini->thermalMitigationEnable) &&
2965 (~VOS_STA & pHddCtx->concurrency_mode) )
2966 {
2967 hddDevTmLevelChangedHandler(pHddCtx->parent_dev, 0);
2968 }
2969
Jeff Johnson295189b2012-06-20 16:38:30 -07002970#ifdef WLAN_BTAMP_FEATURE
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302971 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07002972 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2973 {
2974 //we are ok to do AMP
2975 pHddCtx->isAmpAllowed = VOS_TRUE;
2976 }
2977#endif //WLAN_BTAMP_FEATURE
2978 EXIT();
2979 return 0;
2980}
2981
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002982#ifdef FEATURE_WLAN_TDLS
2983static int wlan_hdd_tdls_add_station(struct wiphy *wiphy,
2984 struct net_device *dev, u8 *mac, bool update, tCsrStaParams *StaParams)
2985{
2986 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2987 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2988 VOS_STATUS status;
Hoonki Lee5305c3a2013-04-29 23:28:59 -07002989 hddTdlsPeer_t *pTdlsPeer;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002990
2991 ENTER();
2992
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05302993 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002994 {
2995 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2996 "Invalid arguments");
2997 return -EINVAL;
2998 }
Hoonki Lee27511902013-03-14 18:19:06 -07002999
3000 if ((eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) ||
3001 (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode))
3002 {
3003 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3004 "%s: TDLS mode is disabled OR not enabled in FW."
3005 MAC_ADDRESS_STR " Request declined.",
3006 __func__, MAC_ADDR_ARRAY(mac));
3007 return -ENOTSUPP;
3008 }
3009
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003010 if (pHddCtx->isLogpInProgress)
3011 {
3012 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3013 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07003014 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003015 return -EBUSY;
3016 }
3017
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05303018 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003019
3020 if ( NULL == pTdlsPeer ) {
3021 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3022 "%s: " MAC_ADDRESS_STR " (update %d) not exist. return invalid",
3023 __func__, MAC_ADDR_ARRAY(mac), update);
3024 return -EINVAL;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07003025 }
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003026
3027 /* in add station, we accept existing valid staId if there is */
3028 if ((0 == update) &&
3029 ((pTdlsPeer->link_status >= eTDLS_LINK_CONNECTING) ||
3030 (TDLS_STA_INDEX_VALID(pTdlsPeer->staId))))
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003031 {
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003032 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003033 "%s: " MAC_ADDRESS_STR
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003034 " link_status %d. staId %d. add station ignored.",
3035 __func__, MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status, pTdlsPeer->staId);
3036 return 0;
3037 }
3038 /* in change station, we accept only when staId is valid */
3039 if ((1 == update) &&
3040 ((pTdlsPeer->link_status > eTDLS_LINK_CONNECTING) ||
3041 (!TDLS_STA_INDEX_VALID(pTdlsPeer->staId))))
3042 {
3043 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3044 "%s: " MAC_ADDRESS_STR
3045 " link status %d. staId %d. change station %s.",
3046 __func__, MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status, pTdlsPeer->staId,
3047 (TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) ? "ignored" : "declined");
3048 return (TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) ? 0 : -EPERM;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003049 }
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07003050
3051 /* when others are on-going, we want to change link_status to idle */
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05303052 if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, mac, TRUE))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003053 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003054 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3055 "%s: " MAC_ADDRESS_STR
3056 " TDLS setup is ongoing. Request declined.",
3057 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07003058 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003059 }
3060
3061 /* first to check if we reached to maximum supported TDLS peer.
3062 TODO: for now, return -EPERM looks working fine,
3063 but need to check if any other errno fit into this category.*/
3064 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
3065 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003066 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3067 "%s: " MAC_ADDRESS_STR
3068 " TDLS Max peer already connected. Request declined.",
3069 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07003070 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003071 }
3072 else
3073 {
3074 hddTdlsPeer_t *pTdlsPeer;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05303075 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003076 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003077 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003078 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3079 "%s: " MAC_ADDRESS_STR " already connected. Request declined.",
3080 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003081 return -EPERM;
3082 }
3083 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003084 if (0 == update)
3085 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_CONNECTING);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003086
Jeff Johnsond75fe012013-04-06 10:53:06 -07003087 /* debug code */
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05303088 if (NULL != StaParams)
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003089 {
3090 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3091 "%s: TDLS Peer Parameters.", __func__);
Hoonki Lee66b75f32013-04-16 18:30:07 -07003092 if(StaParams->htcap_present)
3093 {
3094 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3095 "ht_capa->cap_info: %0x", StaParams->HTCap.capInfo);
3096 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3097 "ht_capa->extended_capabilities: %0x",
3098 StaParams->HTCap.extendedHtCapInfo);
3099 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003100 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3101 "params->capability: %0x",StaParams->capability);
3102 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3103 "params->ext_capab_len: %0x",StaParams->extn_capability);
Hoonki Lee66b75f32013-04-16 18:30:07 -07003104 if(StaParams->vhtcap_present)
3105 {
3106 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3107 "rxMcsMap %x rxHighest %x txMcsMap %x txHighest %x",
3108 StaParams->VHTCap.suppMcs.rxMcsMap, StaParams->VHTCap.suppMcs.rxHighest,
3109 StaParams->VHTCap.suppMcs.txMcsMap, StaParams->VHTCap.suppMcs.txHighest);
3110 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003111 {
3112 int i = 0;
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003113 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "Supported rates:");
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003114 for (i = 0; i < sizeof(StaParams->supported_rates); i++)
3115 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3116 "[%d]: %x ", i, StaParams->supported_rates[i]);
3117 }
Jeff Johnsond75fe012013-04-06 10:53:06 -07003118 } /* end debug code */
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05303119 else if ((1 == update) && (NULL == StaParams))
3120 {
3121 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3122 "%s : update is true, but staParams is NULL. Error!", __func__);
3123 return -EPERM;
3124 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003125
3126 INIT_COMPLETION(pAdapter->tdls_add_station_comp);
3127
3128 if (!update)
3129 {
3130 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
3131 pAdapter->sessionId, mac);
3132 }
3133 else
3134 {
3135 status = sme_ChangeTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
3136 pAdapter->sessionId, mac, StaParams);
3137 }
3138
3139 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_add_station_comp,
3140 msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
3141
3142 if (!status)
3143 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003144 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003145 "%s: timeout waiting for tdls add station indication",
3146 __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07003147 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003148 }
3149 if ( eHAL_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus)
3150 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003151 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003152 "%s: Add Station is unsucessful", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07003153 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003154 }
3155
3156 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07003157
3158error:
3159 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
3160 return -EPERM;
3161
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003162}
3163#endif
3164
Jeff Johnson295189b2012-06-20 16:38:30 -07003165static int wlan_hdd_change_station(struct wiphy *wiphy,
3166 struct net_device *dev,
3167 u8 *mac,
3168 struct station_parameters *params)
3169{
3170 VOS_STATUS status = VOS_STATUS_SUCCESS;
3171 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Gopichand Nakkala29149562013-05-10 21:43:41 +05303172 hdd_context_t *pHddCtx;
3173 hdd_station_ctx_t *pHddStaCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003174 v_MACADDR_t STAMacAddress;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003175#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003176 tCsrStaParams StaParams = {0};
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003177 tANI_U8 isBufSta = 0;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003178#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003179 ENTER();
3180
Gopichand Nakkala29149562013-05-10 21:43:41 +05303181 if ((NULL == pAdapter))
3182 {
3183 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3184 "invalid adapter ");
3185 return -EINVAL;
3186 }
3187
3188 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3189 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3190
3191 if ((NULL == pHddCtx) || (NULL == pHddStaCtx))
3192 {
3193 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3194 "invalid HDD state or HDD station context");
3195 return -EINVAL;
3196 }
3197
3198 if (pHddCtx->isLogpInProgress)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003199 {
3200 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3201 "%s:LOGP in Progress. Ignore!!!", __func__);
3202 return -EAGAIN;
3203 }
3204
Jeff Johnson295189b2012-06-20 16:38:30 -07003205 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
3206
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003207 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3208 || (pAdapter->device_mode == WLAN_HDD_P2P_GO))
Jeff Johnson295189b2012-06-20 16:38:30 -07003209 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003210 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
Jeff Johnson295189b2012-06-20 16:38:30 -07003211 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303212 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
Jeff Johnson295189b2012-06-20 16:38:30 -07003213 WLANTL_STA_AUTHENTICATED);
3214
Gopichand Nakkala29149562013-05-10 21:43:41 +05303215 if (status != VOS_STATUS_SUCCESS)
3216 {
3217 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3218 "%s: Not able to change TL state to AUTHENTICATED", __func__);
3219 return -EINVAL;
3220 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003221 }
3222 }
Hoonki Leea6d49be2013-04-05 09:43:25 -07003223 else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3224 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) {
Gopichand Nakkala29149562013-05-10 21:43:41 +05303225#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003226 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
3227 StaParams.capability = params->capability;
3228 StaParams.uapsd_queues = params->uapsd_queues;
3229 StaParams.max_sp = params->max_sp;
3230
3231 if (0 != params->ext_capab_len)
3232 vos_mem_copy(StaParams.extn_capability, params->ext_capab,
3233 sizeof(StaParams.extn_capability));
3234
3235 if (NULL != params->ht_capa)
Hoonki Lee66b75f32013-04-16 18:30:07 -07003236 {
3237 StaParams.htcap_present = 1;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003238 vos_mem_copy(&StaParams.HTCap, params->ht_capa, sizeof(tSirHTCap));
Hoonki Lee66b75f32013-04-16 18:30:07 -07003239 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003240
3241 StaParams.supported_rates_len = params->supported_rates_len;
3242
3243 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
3244 * The supported_rates array , for all the structures propogating till Add Sta
3245 * to the firmware has to be modified , if the supplicant (ieee80211) is
3246 * modified to send more rates.
3247 */
3248
3249 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
3250 */
3251 if (StaParams.supported_rates_len > SIR_MAC_MAX_SUPP_RATES)
3252 StaParams.supported_rates_len = SIR_MAC_MAX_SUPP_RATES;
3253
3254 if (0 != StaParams.supported_rates_len) {
3255 int i = 0;
3256 vos_mem_copy(StaParams.supported_rates, params->supported_rates,
3257 StaParams.supported_rates_len);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003258 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003259 "Supported Rates with Length %d", StaParams.supported_rates_len);
3260 for (i=0; i < StaParams.supported_rates_len; i++)
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003261 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003262 "[%d]: %0x", i, StaParams.supported_rates[i]);
3263 }
3264
3265 if (NULL != params->vht_capa)
Hoonki Lee66b75f32013-04-16 18:30:07 -07003266 {
3267 StaParams.vhtcap_present = 1;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003268 vos_mem_copy(&StaParams.VHTCap, params->vht_capa, sizeof(tSirVHTCap));
Hoonki Lee66b75f32013-04-16 18:30:07 -07003269 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003270
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003271 if (0 != params->ext_capab_len ) {
3272 /*Define A Macro : TODO Sunil*/
3273 if ((1<<4) & StaParams.extn_capability[3]) {
3274 isBufSta = 1;
3275 }
3276 }
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303277 status = wlan_hdd_tdls_set_peer_caps( pAdapter, mac, params->uapsd_queues,
3278 params->max_sp, isBufSta);
3279 if (VOS_STATUS_SUCCESS != status) {
3280 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3281 "%s: wlan_hdd_tdls_set_peer_caps failed!", __func__);
3282 return -EINVAL;
3283 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003284 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 1, &StaParams);
3285
3286 if (VOS_STATUS_SUCCESS != status) {
3287 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3288 "%s: sme_ChangeTdlsPeerSta failed!", __func__);
3289 return -EINVAL;
3290 }
3291 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003292#endif
Gopichand Nakkala6239acd2013-06-14 14:48:00 +05303293 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003294 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003295 return status;
3296}
3297
3298/*
Jeff Johnson295189b2012-06-20 16:38:30 -07003299 * FUNCTION: wlan_hdd_cfg80211_add_key
3300 * This function is used to initialize the key information
3301 */
3302#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003303static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003304 struct net_device *ndev,
3305 u8 key_index, bool pairwise,
3306 const u8 *mac_addr,
3307 struct key_params *params
3308 )
3309#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003310static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003311 struct net_device *ndev,
3312 u8 key_index, const u8 *mac_addr,
3313 struct key_params *params
3314 )
3315#endif
3316{
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003317 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003318 tCsrRoamSetKey setKey;
3319 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303320 int status;
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003321 v_U32_t roamId= 0xFF;
3322 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003323 hdd_hostapd_state_t *pHostapdState;
3324 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003325 eHalStatus halStatus;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303326 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003327
3328 ENTER();
3329
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303330 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3331 status = wlan_hdd_validate_context(pHddCtx);
3332
3333 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003334 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303335 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3336 "%s: HDD context is not valid", __func__);
3337 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003338 }
3339
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003340 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
3341 __func__, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003342
3343 if (CSR_MAX_NUM_KEY <= key_index)
3344 {
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003345 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003346 key_index);
3347
3348 return -EINVAL;
3349 }
3350
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003351 if (CSR_MAX_KEY_LEN < params->key_len)
3352 {
3353 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key length %d", __func__,
3354 params->key_len);
3355
3356 return -EINVAL;
3357 }
3358
3359 hddLog(VOS_TRACE_LEVEL_INFO,
3360 "%s: called with key index = %d & key length %d",
3361 __func__, key_index, params->key_len);
Jeff Johnson295189b2012-06-20 16:38:30 -07003362
3363 /*extract key idx, key len and key*/
3364 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3365 setKey.keyId = key_index;
3366 setKey.keyLength = params->key_len;
3367 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
3368
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003369 switch (params->cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07003370 {
3371 case WLAN_CIPHER_SUITE_WEP40:
3372 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
3373 break;
3374
3375 case WLAN_CIPHER_SUITE_WEP104:
3376 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
3377 break;
3378
3379 case WLAN_CIPHER_SUITE_TKIP:
3380 {
3381 u8 *pKey = &setKey.Key[0];
3382 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
3383
3384 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
3385
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003386 /*Supplicant sends the 32bytes key in this order
Jeff Johnson295189b2012-06-20 16:38:30 -07003387
3388 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003389 | Tk1 |TX-MIC | RX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003390 |--------------|----------|----------|
3391 <---16bytes---><--8bytes--><--8bytes-->
3392
3393 */
3394 /*Sme expects the 32 bytes key to be in the below order
3395
3396 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003397 | Tk1 |RX-MIC | TX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003398 |--------------|----------|----------|
3399 <---16bytes---><--8bytes--><--8bytes-->
3400 */
3401 /* Copy the Temporal Key 1 (TK1) */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003402 vos_mem_copy(pKey, params->key, 16);
Jeff Johnson295189b2012-06-20 16:38:30 -07003403
3404 /*Copy the rx mic first*/
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003405 vos_mem_copy(&pKey[16], &params->key[24], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003406
3407 /*Copy the tx mic */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003408 vos_mem_copy(&pKey[24], &params->key[16], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003409
3410
3411 break;
3412 }
3413
3414 case WLAN_CIPHER_SUITE_CCMP:
3415 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
3416 break;
3417
3418#ifdef FEATURE_WLAN_WAPI
3419 case WLAN_CIPHER_SUITE_SMS4:
3420 {
3421 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3422 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
3423 params->key, params->key_len);
3424 return 0;
3425 }
3426#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003427
Jeff Johnson295189b2012-06-20 16:38:30 -07003428#ifdef FEATURE_WLAN_CCX
3429 case WLAN_CIPHER_SUITE_KRK:
3430 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
3431 break;
3432#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003433
3434#ifdef WLAN_FEATURE_11W
3435 case WLAN_CIPHER_SUITE_AES_CMAC:
3436 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
Chet Lanctot3b5158a2013-03-31 16:45:21 -07003437 break;
Chet Lanctot186b5732013-03-18 10:26:30 -07003438#endif
3439
Jeff Johnson295189b2012-06-20 16:38:30 -07003440 default:
3441 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
3442 __func__, params->cipher);
3443 return -EOPNOTSUPP;
3444 }
3445
3446 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
3447 __func__, setKey.encType);
3448
Shailender Karmuchi642e9812013-05-30 14:34:49 -07003449 if (
Jeff Johnson295189b2012-06-20 16:38:30 -07003450#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3451 (!pairwise)
3452#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003453 (!mac_addr || is_broadcast_ether_addr(mac_addr))
Jeff Johnson295189b2012-06-20 16:38:30 -07003454#endif
Shailender Karmuchi642e9812013-05-30 14:34:49 -07003455 )
3456 {
3457 /* set group key*/
3458 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3459 "%s- %d: setting Broadcast key",
3460 __func__, __LINE__);
3461 setKey.keyDirection = eSIR_RX_ONLY;
3462 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3463 }
3464 else
3465 {
3466 /* set pairwise key*/
3467 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3468 "%s- %d: setting pairwise key",
3469 __func__, __LINE__);
3470 setKey.keyDirection = eSIR_TX_RX;
3471 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3472 }
3473 if ((WLAN_HDD_IBSS == pAdapter->device_mode) && !pairwise)
3474 {
3475 setKey.keyDirection = eSIR_TX_RX;
3476 /*Set the group key*/
3477 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3478 pAdapter->sessionId, &setKey, &roamId );
Jeff Johnson295189b2012-06-20 16:38:30 -07003479
Shailender Karmuchi642e9812013-05-30 14:34:49 -07003480 if ( 0 != status )
3481 {
3482 hddLog(VOS_TRACE_LEVEL_ERROR,
3483 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3484 return -EINVAL;
3485 }
3486 /*Save the keys here and call sme_RoamSetKey for setting
3487 the PTK after peer joins the IBSS network*/
3488 vos_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
3489 &setKey, sizeof(tCsrRoamSetKey));
3490 return status;
3491 }
Gopichand Nakkala29149562013-05-10 21:43:41 +05303492 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) ||
3493 (pAdapter->device_mode == WLAN_HDD_P2P_GO))
3494 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003495 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003496 if( pHostapdState->bssState == BSS_START )
3497 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003498 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3499
3500 if ( status != eHAL_STATUS_SUCCESS )
3501 {
3502 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3503 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3504 __LINE__, status );
3505 }
3506 }
3507
3508 /* Saving WEP keys */
3509 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
3510 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
3511 {
3512 //Save the wep key in ap context. Issue setkey after the BSS is started.
3513 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3514 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
3515 }
3516 else
3517 {
3518 //Save the key in ap context. Issue setkey after the BSS is started.
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003519 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003520 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
3521 }
3522 }
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003523 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
3524 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) )
Jeff Johnson295189b2012-06-20 16:38:30 -07003525 {
3526 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3527 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3528
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303529#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3530 if (!pairwise)
3531#else
3532 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
3533#endif
3534 {
3535 /* set group key*/
3536 if (pHddStaCtx->roam_info.deferKeyComplete)
3537 {
3538 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3539 "%s- %d: Perform Set key Complete",
3540 __func__, __LINE__);
3541 hdd_PerformRoamSetKeyComplete(pAdapter);
3542 }
3543 }
3544
Jeff Johnson295189b2012-06-20 16:38:30 -07003545 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
3546
Venkata Prathyusha Kuntupalliee2ce712013-01-17 14:09:24 -08003547 pWextState->roamProfile.Keys.defaultIndex = key_index;
3548
3549
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003550 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07003551 params->key, params->key_len);
3552
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303553
Jeff Johnson295189b2012-06-20 16:38:30 -07003554 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3555
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303556 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07003557 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303558 __func__, setKey.peerMac[0], setKey.peerMac[1],
3559 setKey.peerMac[2], setKey.peerMac[3],
3560 setKey.peerMac[4], setKey.peerMac[5],
Jeff Johnson295189b2012-06-20 16:38:30 -07003561 setKey.keyDirection);
3562
3563 vos_status = wlan_hdd_check_ula_done(pAdapter);
3564
3565 if ( vos_status != VOS_STATUS_SUCCESS )
3566 {
3567 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3568 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
3569 __LINE__, vos_status );
3570
3571 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3572
3573 return -EINVAL;
3574
3575 }
3576
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003577#ifdef WLAN_FEATURE_VOWIFI_11R
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303578 /* The supplicant may attempt to set the PTK once pre-authentication
3579 is done. Save the key in the UMAC and include it in the ADD BSS
3580 request */
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003581 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303582 if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS )
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003583 {
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303584 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3585 "%s: Update PreAuth Key success", __func__);
3586 return 0;
3587 }
3588 else if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_FAILED )
3589 {
3590 hddLog(VOS_TRACE_LEVEL_ERROR,
3591 "%s: Update PreAuth Key failed", __func__);
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303592 return -EINVAL;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003593 }
3594#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07003595
3596 /* issue set key request to SME*/
3597 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3598 pAdapter->sessionId, &setKey, &roamId );
3599
3600 if ( 0 != status )
3601 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303602 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003603 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3604 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3605 return -EINVAL;
3606 }
3607
3608
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303609 /* in case of IBSS as there was no information available about WEP keys during
3610 * IBSS join, group key intialized with NULL key, so re-initialize group key
Jeff Johnson295189b2012-06-20 16:38:30 -07003611 * with correct value*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303612 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
3613 !( ( IW_AUTH_KEY_MGMT_802_1X
3614 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
Jeff Johnson295189b2012-06-20 16:38:30 -07003615 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3616 )
3617 &&
3618 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3619 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3620 )
3621 )
3622 {
3623 setKey.keyDirection = eSIR_RX_ONLY;
3624 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3625
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303626 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07003627 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303628 __func__, setKey.peerMac[0], setKey.peerMac[1],
3629 setKey.peerMac[2], setKey.peerMac[3],
3630 setKey.peerMac[4], setKey.peerMac[5],
Jeff Johnson295189b2012-06-20 16:38:30 -07003631 setKey.keyDirection);
3632
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303633 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07003634 pAdapter->sessionId, &setKey, &roamId );
3635
3636 if ( 0 != status )
3637 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303638 hddLog(VOS_TRACE_LEVEL_ERROR,
3639 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07003640 __func__, status);
3641 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3642 return -EINVAL;
3643 }
3644 }
3645 }
3646
3647 return 0;
3648}
3649
3650/*
3651 * FUNCTION: wlan_hdd_cfg80211_get_key
3652 * This function is used to get the key information
3653 */
3654#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303655static int wlan_hdd_cfg80211_get_key(
3656 struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003657 struct net_device *ndev,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303658 u8 key_index, bool pairwise,
Jeff Johnson295189b2012-06-20 16:38:30 -07003659 const u8 *mac_addr, void *cookie,
3660 void (*callback)(void *cookie, struct key_params*)
3661 )
3662#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303663static int wlan_hdd_cfg80211_get_key(
3664 struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003665 struct net_device *ndev,
3666 u8 key_index, const u8 *mac_addr, void *cookie,
3667 void (*callback)(void *cookie, struct key_params*)
3668 )
3669#endif
3670{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303671 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003672 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3673 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
3674 struct key_params params;
3675
3676 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303677
Jeff Johnson295189b2012-06-20 16:38:30 -07003678 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3679 __func__,pAdapter->device_mode);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303680
Jeff Johnson295189b2012-06-20 16:38:30 -07003681 memset(&params, 0, sizeof(params));
3682
3683 if (CSR_MAX_NUM_KEY <= key_index)
3684 {
3685 return -EINVAL;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303686 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003687
3688 switch(pRoamProfile->EncryptionType.encryptionType[0])
3689 {
3690 case eCSR_ENCRYPT_TYPE_NONE:
3691 params.cipher = IW_AUTH_CIPHER_NONE;
3692 break;
3693
3694 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3695 case eCSR_ENCRYPT_TYPE_WEP40:
3696 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3697 break;
3698
3699 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3700 case eCSR_ENCRYPT_TYPE_WEP104:
3701 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3702 break;
3703
3704 case eCSR_ENCRYPT_TYPE_TKIP:
3705 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3706 break;
3707
3708 case eCSR_ENCRYPT_TYPE_AES:
3709 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3710 break;
3711
3712 default:
3713 params.cipher = IW_AUTH_CIPHER_NONE;
3714 break;
3715 }
3716
3717 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3718 params.seq_len = 0;
3719 params.seq = NULL;
3720 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3721 callback(cookie, &params);
3722 return 0;
3723}
3724
3725/*
3726 * FUNCTION: wlan_hdd_cfg80211_del_key
3727 * This function is used to delete the key information
3728 */
3729#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303730static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003731 struct net_device *ndev,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303732 u8 key_index,
3733 bool pairwise,
Jeff Johnson295189b2012-06-20 16:38:30 -07003734 const u8 *mac_addr
3735 )
3736#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303737static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003738 struct net_device *ndev,
3739 u8 key_index,
3740 const u8 *mac_addr
3741 )
3742#endif
3743{
3744 int status = 0;
3745
3746 //This code needs to be revisited. There is sme_removeKey API, we should
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303747 //plan to use that. After the change to use correct index in setkey,
Jeff Johnson295189b2012-06-20 16:38:30 -07003748 //it is observed that this is invalidating peer
3749 //key index whenever re-key is done. This is affecting data link.
3750 //It should be ok to ignore del_key.
3751#if 0
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303752 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3753 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003754 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3755 tCsrRoamSetKey setKey;
3756 v_U32_t roamId= 0xFF;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303757
Jeff Johnson295189b2012-06-20 16:38:30 -07003758 ENTER();
3759
3760 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3761 __func__,pAdapter->device_mode);
3762
3763 if (CSR_MAX_NUM_KEY <= key_index)
3764 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303765 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003766 key_index);
3767
3768 return -EINVAL;
3769 }
3770
3771 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3772 setKey.keyId = key_index;
3773
3774 if (mac_addr)
3775 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3776 else
3777 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3778
3779 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3780
3781 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003782 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303783 )
3784 {
3785
3786 hdd_hostapd_state_t *pHostapdState =
Jeff Johnson295189b2012-06-20 16:38:30 -07003787 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3788 if( pHostapdState->bssState == BSS_START)
3789 {
3790 status = WLANSAP_SetKeySta( pVosContext, &setKey);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303791
Jeff Johnson295189b2012-06-20 16:38:30 -07003792 if ( status != eHAL_STATUS_SUCCESS )
3793 {
3794 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3795 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3796 __LINE__, status );
3797 }
3798 }
3799 }
3800 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303801 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003802 )
3803 {
3804 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3805
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303806 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3807
3808 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07003809 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303810 __func__, setKey.peerMac[0], setKey.peerMac[1],
3811 setKey.peerMac[2], setKey.peerMac[3],
Jeff Johnson295189b2012-06-20 16:38:30 -07003812 setKey.peerMac[4], setKey.peerMac[5]);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303813 if(pAdapter->sessionCtx.station.conn_info.connState ==
3814 eConnectionState_Associated)
Jeff Johnson295189b2012-06-20 16:38:30 -07003815 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303816 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07003817 pAdapter->sessionId, &setKey, &roamId );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303818
Jeff Johnson295189b2012-06-20 16:38:30 -07003819 if ( 0 != status )
3820 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303821 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003822 "%s: sme_RoamSetKey failure, returned %d",
3823 __func__, status);
3824 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3825 return -EINVAL;
3826 }
3827 }
3828 }
3829#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003830 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003831 return status;
3832}
3833
3834/*
3835 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3836 * This function is used to set the default tx key index
3837 */
3838#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3839static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3840 struct net_device *ndev,
3841 u8 key_index,
3842 bool unicast, bool multicast)
3843#else
3844static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3845 struct net_device *ndev,
3846 u8 key_index)
3847#endif
3848{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303849 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303850 int status;
Gopichand Nakkala29149562013-05-10 21:43:41 +05303851 hdd_wext_state_t *pWextState;
3852 hdd_station_ctx_t *pHddStaCtx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303853 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003854
3855 ENTER();
3856
Gopichand Nakkala29149562013-05-10 21:43:41 +05303857 if ((NULL == pAdapter))
3858 {
3859 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3860 "invalid adapter");
3861 return -EINVAL;
3862 }
3863
3864 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3865 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3866
3867 if ((NULL == pWextState) || (NULL == pHddStaCtx))
3868 {
3869 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3870 "invalid Wext state or HDD context");
3871 return -EINVAL;
3872 }
3873
Jeff Johnson295189b2012-06-20 16:38:30 -07003874 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3875 __func__,pAdapter->device_mode, key_index);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303876
Jeff Johnson295189b2012-06-20 16:38:30 -07003877 if (CSR_MAX_NUM_KEY <= key_index)
3878 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303879 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003880 key_index);
3881
3882 return -EINVAL;
3883 }
3884
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303885 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3886 status = wlan_hdd_validate_context(pHddCtx);
3887
3888 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003889 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303890 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3891 "%s: HDD context is not valid", __func__);
3892 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003893 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303894
Jeff Johnson295189b2012-06-20 16:38:30 -07003895 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003896 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303897 )
Jeff Johnson295189b2012-06-20 16:38:30 -07003898 {
Gopichand Nakkala29149562013-05-10 21:43:41 +05303899 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
Jeff Johnson295189b2012-06-20 16:38:30 -07003900 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303901 (eCSR_ENCRYPT_TYPE_AES !=
Jeff Johnson295189b2012-06-20 16:38:30 -07003902 pWextState->roamProfile.EncryptionType.encryptionType[0])
3903 )
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303904 {
3905 /* if default key index is not same as previous one,
Jeff Johnson295189b2012-06-20 16:38:30 -07003906 * then update the default key index */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303907
Jeff Johnson295189b2012-06-20 16:38:30 -07003908 tCsrRoamSetKey setKey;
3909 v_U32_t roamId= 0xFF;
3910 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303911
3912 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07003913 __func__, key_index);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303914
Jeff Johnson295189b2012-06-20 16:38:30 -07003915 Keys->defaultIndex = (u8)key_index;
3916 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3917 setKey.keyId = key_index;
3918 setKey.keyLength = Keys->KeyLength[key_index];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303919
3920 vos_mem_copy(&setKey.Key[0],
3921 &Keys->KeyMaterial[key_index][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07003922 Keys->KeyLength[key_index]);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303923
Gopichand Nakkala29149562013-05-10 21:43:41 +05303924 setKey.keyDirection = eSIR_TX_RX;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303925
3926 vos_mem_copy(setKey.peerMac,
Jeff Johnson295189b2012-06-20 16:38:30 -07003927 &pHddStaCtx->conn_info.bssId[0],
3928 WNI_CFG_BSSID_LEN);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303929
Gopichand Nakkala29149562013-05-10 21:43:41 +05303930 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
3931 pWextState->roamProfile.EncryptionType.encryptionType[0] ==
3932 eCSR_ENCRYPT_TYPE_WEP104)
3933 {
3934 /*In the case of dynamic wep supplicant hardcodes DWEP type to eCSR_ENCRYPT_TYPE_WEP104
3935 even though ap is configured for WEP-40 encryption. In this canse the key length
3936 is 5 but the encryption type is 104 hence checking the key langht(5) and encryption
3937 type(104) and switching encryption type to 40*/
3938 pWextState->roamProfile.EncryptionType.encryptionType[0] =
3939 eCSR_ENCRYPT_TYPE_WEP40;
3940 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
3941 eCSR_ENCRYPT_TYPE_WEP40;
3942 }
3943
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303944 setKey.encType =
Jeff Johnson295189b2012-06-20 16:38:30 -07003945 pWextState->roamProfile.EncryptionType.encryptionType[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303946
Jeff Johnson295189b2012-06-20 16:38:30 -07003947 /* issue set key request */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303948 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07003949 pAdapter->sessionId, &setKey, &roamId );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303950
Jeff Johnson295189b2012-06-20 16:38:30 -07003951 if ( 0 != status )
3952 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303953 hddLog(VOS_TRACE_LEVEL_ERROR,
3954 "%s: sme_RoamSetKey failed, returned %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003955 status);
3956 return -EINVAL;
3957 }
3958 }
3959 }
3960
3961 /* In SoftAp mode setting key direction for default mode */
3962 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3963 {
3964 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3965 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3966 (eCSR_ENCRYPT_TYPE_AES !=
3967 pWextState->roamProfile.EncryptionType.encryptionType[0])
3968 )
3969 {
3970 /* Saving key direction for default key index to TX default */
3971 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3972 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3973 }
3974 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303975
Jeff Johnson295189b2012-06-20 16:38:30 -07003976 return status;
3977}
3978
Jeff Johnson295189b2012-06-20 16:38:30 -07003979/*
3980 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3981 * This function is used to inform the BSS details to nl80211 interface.
3982 */
3983static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3984 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3985{
3986 struct net_device *dev = pAdapter->dev;
3987 struct wireless_dev *wdev = dev->ieee80211_ptr;
3988 struct wiphy *wiphy = wdev->wiphy;
3989 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3990 int chan_no;
3991 int ie_length;
3992 const char *ie;
3993 unsigned int freq;
3994 struct ieee80211_channel *chan;
3995 int rssi = 0;
3996 struct cfg80211_bss *bss = NULL;
3997
3998 ENTER();
3999
4000 if( NULL == pBssDesc )
4001 {
4002 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
4003 return bss;
4004 }
4005
4006 chan_no = pBssDesc->channelId;
4007 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
4008 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
4009
4010 if( NULL == ie )
4011 {
4012 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
4013 return bss;
4014 }
4015
4016#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
4017 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
4018 {
4019 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
4020 }
4021 else
4022 {
4023 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
4024 }
4025#else
4026 freq = ieee80211_channel_to_frequency(chan_no);
4027#endif
4028
4029 chan = __ieee80211_get_channel(wiphy, freq);
4030
4031 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
4032 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
4033 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
4034 if (bss == NULL)
4035 {
4036 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
4037
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304038 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
4039 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
Jeff Johnson295189b2012-06-20 16:38:30 -07004040 pBssDesc->capabilityInfo,
4041 pBssDesc->beaconInterval, ie, ie_length,
4042 rssi, GFP_KERNEL ));
4043}
4044 else
4045 {
4046 return bss;
4047 }
4048}
4049
4050
4051
4052/*
4053 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
4054 * This function is used to inform the BSS details to nl80211 interface.
4055 */
4056struct cfg80211_bss*
4057wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
4058 tSirBssDescription *bss_desc
4059 )
4060{
4061 /*
4062 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
4063 already exists in bss data base of cfg80211 for that particular BSS ID.
4064 Using cfg80211_inform_bss_frame to update the bss entry instead of
4065 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
4066 now there is no possibility to get the mgmt(probe response) frame from PE,
4067 converting bss_desc to ieee80211_mgmt(probe response) and passing to
4068 cfg80211_inform_bss_frame.
4069 */
4070 struct net_device *dev = pAdapter->dev;
4071 struct wireless_dev *wdev = dev->ieee80211_ptr;
4072 struct wiphy *wiphy = wdev->wiphy;
4073 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08004074#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
4075 qcom_ie_age *qie_age = NULL;
4076 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
4077#else
Jeff Johnson295189b2012-06-20 16:38:30 -07004078 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08004079#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004080 const char *ie =
4081 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
4082 unsigned int freq;
4083 struct ieee80211_channel *chan;
4084 struct ieee80211_mgmt *mgmt =
4085 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
4086 struct cfg80211_bss *bss_status = NULL;
4087 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
4088 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07004089#ifdef WLAN_OPEN_SOURCE
4090 struct timespec ts;
4091#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004092
4093 ENTER();
4094
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07004095 if (!mgmt)
4096 return NULL;
4097
Jeff Johnson295189b2012-06-20 16:38:30 -07004098 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07004099
4100#ifdef WLAN_OPEN_SOURCE
4101 /* Android does not want the timestamp from the frame.
4102 Instead it wants a monotonic increasing value */
4103 get_monotonic_boottime(&ts);
4104 mgmt->u.probe_resp.timestamp =
4105 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
4106#else
4107 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07004108 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
4109 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07004110
4111#endif
4112
Jeff Johnson295189b2012-06-20 16:38:30 -07004113 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
4114 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08004115
4116#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
4117 /* GPS Requirement: need age ie per entry. Using vendor specific. */
4118 /* Assuming this is the last IE, copy at the end */
4119 ie_length -=sizeof(qcom_ie_age);
4120 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
4121 qie_age->element_id = QCOM_VENDOR_IE_ID;
4122 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
4123 qie_age->oui_1 = QCOM_OUI1;
4124 qie_age->oui_2 = QCOM_OUI2;
4125 qie_age->oui_3 = QCOM_OUI3;
4126 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
4127 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
4128#endif
4129
Jeff Johnson295189b2012-06-20 16:38:30 -07004130 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
Gopichand Nakkalad908ec82013-05-16 19:32:19 +05304131 if (bss_desc->fProbeRsp)
4132 {
4133 mgmt->frame_control |=
4134 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
4135 }
4136 else
4137 {
4138 mgmt->frame_control |=
4139 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
4140 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004141
4142#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304143 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07004144 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
4145 {
4146 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
4147 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304148 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07004149 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
4150
4151 {
4152 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
4153 }
4154 else
4155 {
4156 kfree(mgmt);
4157 return NULL;
4158 }
4159#else
4160 freq = ieee80211_channel_to_frequency(chan_no);
4161#endif
4162 chan = __ieee80211_get_channel(wiphy, freq);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08004163 /*when the band is changed on the fly using the GUI, three things are done
4164 * 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)
4165 * as part of the scan abort, message willbe queued to PE and we proceed with flushing and changinh the band.
4166 * pe will stop the scanning further and report back the results what ever it had till now by calling the call back function.
4167 * if the time between update band and scandone call back is sufficent enough the band change reflects in SME, SME validates the channels
4168 * and discards the channels correponding to previous band and calls back with zero bss results.
4169 * 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
4170 * all the channels correponding to previous band.this is due to race condition.but those channels are invalid to the new band and so
4171 * this function __ieee80211_get_channel will return NULL.Each time we report scan result with this pointer null warning kernel trace is printed.
4172 * if the scan results contain large number of APs continuosly kernel warning trace is printed and it will lead to apps watch dog bark.
4173 * So drop the bss and continue to next bss.
4174 */
4175 if(chan == NULL)
4176 {
4177 hddLog(VOS_TRACE_LEVEL_INFO, "%s chan pointer is NULL", __func__);
Chilam Ngc4244af2013-04-01 15:37:32 -07004178 kfree(mgmt);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08004179 return NULL;
4180 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004181 /*To keep the rssi icon of the connected AP in the scan window
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304182 *and the rssi icon of the wireless networks in sync
Jeff Johnson295189b2012-06-20 16:38:30 -07004183 * */
4184 if (( eConnectionState_Associated ==
4185 pAdapter->sessionCtx.station.conn_info.connState ) &&
4186 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
4187 pAdapter->sessionCtx.station.conn_info.bssId,
4188 WNI_CFG_BSSID_LEN)))
4189 {
4190 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
4191 rssi = (pAdapter->rssi * 100);
4192 }
4193 else
4194 {
4195 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
4196 }
4197
4198 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
4199 frame_len, rssi, GFP_KERNEL);
4200 kfree(mgmt);
4201 return bss_status;
4202}
4203
4204/*
4205 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
4206 * This function is used to update the BSS data base of CFG8011
4207 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304208struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07004209 tCsrRoamInfo *pRoamInfo
4210 )
4211{
4212 tCsrRoamConnectedProfile roamProfile;
4213 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4214 struct cfg80211_bss *bss = NULL;
4215
4216 ENTER();
4217
4218 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
4219 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
4220
4221 if (NULL != roamProfile.pBssDesc)
4222 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304223 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07004224 &roamProfile);
4225
4226 if (NULL == bss)
4227 {
4228 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
4229 __func__);
4230 }
4231
4232 sme_RoamFreeConnectProfile(hHal, &roamProfile);
4233 }
4234 else
4235 {
4236 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
4237 __func__);
4238 }
4239 return bss;
4240}
4241
4242/*
4243 * FUNCTION: wlan_hdd_cfg80211_update_bss
4244 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304245static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
4246 hdd_adapter_t *pAdapter
Jeff Johnson295189b2012-06-20 16:38:30 -07004247 )
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304248{
Jeff Johnson295189b2012-06-20 16:38:30 -07004249 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4250 tCsrScanResultInfo *pScanResult;
4251 eHalStatus status = 0;
4252 tScanResultHandle pResult;
4253 struct cfg80211_bss *bss_status = NULL;
4254
4255 ENTER();
4256
4257 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4258 {
4259 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
4260 return -EAGAIN;
4261 }
4262
4263 /*
4264 * start getting scan results and populate cgf80211 BSS database
4265 */
4266 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
4267
4268 /* no scan results */
4269 if (NULL == pResult)
4270 {
4271 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
4272 return status;
4273 }
4274
4275 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
4276
4277 while (pScanResult)
4278 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304279 /*
4280 * cfg80211_inform_bss() is not updating ie field of bss entry, if
4281 * entry already exists in bss data base of cfg80211 for that
4282 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
4283 * bss entry instead of cfg80211_inform_bss, But this call expects
4284 * mgmt packet as input. As of now there is no possibility to get
4285 * the mgmt(probe response) frame from PE, converting bss_desc to
Jeff Johnson295189b2012-06-20 16:38:30 -07004286 * ieee80211_mgmt(probe response) and passing to c
4287 * fg80211_inform_bss_frame.
4288 * */
4289
4290 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
4291 &pScanResult->BssDescriptor);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304292
Jeff Johnson295189b2012-06-20 16:38:30 -07004293
4294 if (NULL == bss_status)
4295 {
4296 hddLog(VOS_TRACE_LEVEL_INFO,
4297 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
4298 }
4299 else
4300 {
Yue Maf49ba872013-08-19 12:04:25 -07004301 cfg80211_put_bss(
4302#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
4303 wiphy,
4304#endif
4305 bss_status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004306 }
4307
4308 pScanResult = sme_ScanResultGetNext(hHal, pResult);
4309 }
4310
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304311 sme_ScanResultPurge(hHal, pResult);
Jeff Johnson295189b2012-06-20 16:38:30 -07004312
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304313 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004314}
4315
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004316void
4317hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
4318{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304319 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004320 "%02X:%02X:%02X:%02X:%02X:%02X\n",
4321 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
4322 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004323} /****** end hddPrintMacAddr() ******/
4324
4325void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004326hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004327{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304328 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004329 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
4330 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
4331 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
4332 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004333} /****** end hddPrintPmkId() ******/
4334
4335//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
4336//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
4337
4338//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
4339//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
4340
4341#define dump_bssid(bssid) \
4342 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004343 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
4344 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
4345 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004346 }
4347
4348#define dump_pmkid(pMac, pmkid) \
4349 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004350 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
4351 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
4352 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004353 }
4354
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07004355#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004356/*
4357 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
4358 * This function is used to notify the supplicant of a new PMKSA candidate.
4359 */
4360int wlan_hdd_cfg80211_pmksa_candidate_notify(
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304361 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004362 int index, bool preauth )
4363{
Jeff Johnsone7245742012-09-05 17:12:55 -07004364#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004365 struct net_device *dev = pAdapter->dev;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004366 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004367
4368 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07004369 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004370
4371 if( NULL == pRoamInfo )
4372 {
4373 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
4374 return -EINVAL;
4375 }
4376
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004377 if (eANI_BOOLEAN_TRUE == hdd_is_okc_mode_enabled(pHddCtx))
4378 {
4379 dump_bssid(pRoamInfo->bssid);
4380 cfg80211_pmksa_candidate_notify(dev, index,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004381 pRoamInfo->bssid, preauth, GFP_KERNEL);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004382 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004383#endif /* FEATURE_WLAN_OKC */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304384 return 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004385}
4386#endif //FEATURE_WLAN_LFR
4387
Yue Maef608272013-04-08 23:09:17 -07004388#ifdef FEATURE_WLAN_LFR_METRICS
4389/*
4390 * FUNCTION: wlan_hdd_cfg80211_roam_metrics_preauth
4391 * 802.11r/LFR metrics reporting function to report preauth initiation
4392 *
4393 */
4394#define MAX_LFR_METRICS_EVENT_LENGTH 100
4395VOS_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
4396 tCsrRoamInfo *pRoamInfo)
4397{
4398 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
4399 union iwreq_data wrqu;
4400
4401 ENTER();
4402
4403 if (NULL == pAdapter)
4404 {
4405 hddLog(LOGE, "%s: pAdapter is NULL!", __func__);
4406 return VOS_STATUS_E_FAILURE;
4407 }
4408
4409 /* create the event */
4410 memset(&wrqu, 0, sizeof(wrqu));
4411 memset(metrics_notification, 0, sizeof(metrics_notification));
4412
4413 wrqu.data.pointer = metrics_notification;
4414 wrqu.data.length = scnprintf(metrics_notification,
4415 sizeof(metrics_notification), "QCOM: LFR_PREAUTH_INIT "
4416 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(pRoamInfo->bssid));
4417
4418 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, metrics_notification);
4419
4420 EXIT();
4421
4422 return VOS_STATUS_SUCCESS;
4423}
4424
4425/*
4426 * FUNCTION: wlan_hdd_cfg80211_roam_metrics_preauth_status
4427 * 802.11r/LFR metrics reporting function to report preauth completion
4428 * or failure
4429 */
4430VOS_STATUS wlan_hdd_cfg80211_roam_metrics_preauth_status(
4431 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, bool preauth_status)
4432{
4433 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
4434 union iwreq_data wrqu;
4435
4436 ENTER();
4437
4438 if (NULL == pAdapter)
4439 {
4440 hddLog(LOGE, "%s: pAdapter is NULL!", __func__);
4441 return VOS_STATUS_E_FAILURE;
4442 }
4443
4444 /* create the event */
4445 memset(&wrqu, 0, sizeof(wrqu));
4446 memset(metrics_notification, 0, sizeof(metrics_notification));
4447
4448 scnprintf(metrics_notification, sizeof(metrics_notification),
4449 "QCOM: LFR_PREAUTH_STATUS "MAC_ADDRESS_STR,
4450 MAC_ADDR_ARRAY(pRoamInfo->bssid));
4451
4452 if (1 == preauth_status)
4453 strncat(metrics_notification, " TRUE", 5);
4454 else
4455 strncat(metrics_notification, " FALSE", 6);
4456
4457 wrqu.data.pointer = metrics_notification;
4458 wrqu.data.length = strlen(metrics_notification);
4459
4460 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, metrics_notification);
4461
4462 EXIT();
4463
4464 return VOS_STATUS_SUCCESS;
4465}
4466
4467/*
4468 * FUNCTION: wlan_hdd_cfg80211_roam_metrics_handover
4469 * 802.11r/LFR metrics reporting function to report handover initiation
4470 *
4471 */
4472VOS_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t * pAdapter,
4473 tCsrRoamInfo *pRoamInfo)
4474{
4475 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
4476 union iwreq_data wrqu;
4477
4478 ENTER();
4479
4480 if (NULL == pAdapter)
4481 {
4482 hddLog(LOGE, "%s: pAdapter is NULL!", __func__);
4483 return VOS_STATUS_E_FAILURE;
4484 }
4485
4486 /* create the event */
4487 memset(&wrqu, 0, sizeof(wrqu));
4488 memset(metrics_notification, 0, sizeof(metrics_notification));
4489
4490 wrqu.data.pointer = metrics_notification;
4491 wrqu.data.length = scnprintf(metrics_notification,
4492 sizeof(metrics_notification), "QCOM: LFR_PREAUTH_HANDOVER "
4493 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(pRoamInfo->bssid));
4494
4495 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, metrics_notification);
4496
4497 EXIT();
4498
4499 return VOS_STATUS_SUCCESS;
4500}
4501#endif
4502
Jeff Johnson295189b2012-06-20 16:38:30 -07004503/*
4504 * FUNCTION: hdd_cfg80211_scan_done_callback
4505 * scanning callback function, called after finishing scan
4506 *
4507 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304508static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
Jeff Johnson295189b2012-06-20 16:38:30 -07004509 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
4510{
4511 struct net_device *dev = (struct net_device *) pContext;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304512 //struct wireless_dev *wdev = dev->ieee80211_ptr;
Jeff Johnson295189b2012-06-20 16:38:30 -07004513 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004514 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4515 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004516 struct cfg80211_scan_request *req = NULL;
4517 int ret = 0;
4518
4519 ENTER();
4520
4521 hddLog(VOS_TRACE_LEVEL_INFO,
4522 "%s called with halHandle = %p, pContext = %p,"
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304523 "scanID = %d, returned status = %d\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07004524 __func__, halHandle, pContext, (int) scanId, (int) status);
4525
4526 //Block on scan req completion variable. Can't wait forever though.
4527 ret = wait_for_completion_interruptible_timeout(
4528 &pScanInfo->scan_req_completion_event,
4529 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
4530 if (!ret)
4531 {
4532 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004533 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004534 }
4535
Yue Maef608272013-04-08 23:09:17 -07004536 if (pScanInfo->mScanPending != VOS_TRUE)
Jeff Johnson295189b2012-06-20 16:38:30 -07004537 {
4538 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004539 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004540 }
4541
4542 /* Check the scanId */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304543 if (pScanInfo->scanId != scanId)
Jeff Johnson295189b2012-06-20 16:38:30 -07004544 {
4545 hddLog(VOS_TRACE_LEVEL_INFO,
4546 "%s called with mismatched scanId pScanInfo->scanId = %d "
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304547 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
Jeff Johnson295189b2012-06-20 16:38:30 -07004548 (int) scanId);
4549 }
4550
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304551 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07004552 pAdapter);
4553
4554 if (0 > ret)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304555 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004556
4557
4558 /* If any client wait scan result through WEXT
4559 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004560 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07004561 {
4562 /* The other scan request waiting for current scan finish
4563 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004564 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004565 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004566 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004567 }
4568 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004569 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004570 {
4571 struct net_device *dev = pAdapter->dev;
4572 union iwreq_data wrqu;
4573 int we_event;
4574 char *msg;
4575
4576 memset(&wrqu, '\0', sizeof(wrqu));
4577 we_event = SIOCGIWSCAN;
4578 msg = NULL;
4579 wireless_send_event(dev, we_event, &wrqu, msg);
4580 }
4581 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004582 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004583
4584 /* Get the Scan Req */
4585 req = pAdapter->request;
4586
4587 if (!req)
4588 {
4589 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004590 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07004591 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004592 }
4593
4594 /*
4595 * setting up 0, just in case.
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304596 */
Jeff Johnson295189b2012-06-20 16:38:30 -07004597 req->n_ssids = 0;
4598 req->n_channels = 0;
4599 req->ie = 0;
4600
Jeff Johnson295189b2012-06-20 16:38:30 -07004601 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004602 /* Scan is no longer pending */
4603 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004604
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07004605 /*
4606 * cfg80211_scan_done informing NL80211 about completion
4607 * of scanning
4608 */
4609 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004610 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004611
Jeff Johnsone7245742012-09-05 17:12:55 -07004612allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004613 /* release the wake lock at the end of the scan*/
4614 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004615
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004616 /* Acquire wakelock to handle the case where APP's tries to suspend
4617 * immediatly after the driver gets connect request(i.e after scan)
4618 * from supplicant, this result in app's is suspending and not able
4619 * to process the connect request to AP */
Amar Singhal6144c002013-05-03 16:11:42 -07004620 hdd_allow_suspend_timeout(1000);
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004621
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004622#ifdef FEATURE_WLAN_TDLS
4623 wlan_hdd_tdls_scan_done_callback(pAdapter);
4624#endif
4625
Jeff Johnson295189b2012-06-20 16:38:30 -07004626 EXIT();
4627 return 0;
4628}
4629
4630/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004631 * FUNCTION: hdd_isScanAllowed
4632 * Go through each adapter and check if scan allowed
4633 *
4634 */
4635v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
4636{
4637 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4638 hdd_station_ctx_t *pHddStaCtx = NULL;
4639 hdd_adapter_t *pAdapter = NULL;
4640 VOS_STATUS status = 0;
4641 v_U8_t staId = 0;
4642 v_U8_t *staMac = NULL;
4643
4644 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4645
4646 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4647 {
4648 pAdapter = pAdapterNode->pAdapter;
4649
4650 if( pAdapter )
4651 {
4652 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304653 "%s: Adapter with device mode %d exists",
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004654 __func__, pAdapter->device_mode);
4655 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4656 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4657 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
4658 {
4659 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4660 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
4661 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
4662 {
4663 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
4664 hddLog(VOS_TRACE_LEVEL_ERROR,
4665 "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the "
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304666 "middle of WPS/EAPOL exchange.", __func__,
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004667 staMac[0], staMac[1], staMac[2],
4668 staMac[3], staMac[4], staMac[5]);
4669 return VOS_FALSE;
4670 }
4671 }
4672 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
4673 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
4674 {
4675 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
4676 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304677 if ((pAdapter->aStaInfo[staId].isUsed) &&
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004678 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
4679 {
4680 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
4681
4682 hddLog(VOS_TRACE_LEVEL_ERROR,
4683 "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the "
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304684 "middle of WPS/EAPOL exchange.", __func__,
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004685 staMac[0], staMac[1], staMac[2],
4686 staMac[3], staMac[4], staMac[5]);
4687 return VOS_FALSE;
4688 }
4689 }
4690 }
4691 }
4692 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4693 pAdapterNode = pNext;
4694 }
4695 hddLog(VOS_TRACE_LEVEL_INFO,
4696 "%s: Scan allowed", __func__);
4697 return VOS_TRUE;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304698}
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004699
4700/*
Jeff Johnson295189b2012-06-20 16:38:30 -07004701 * FUNCTION: wlan_hdd_cfg80211_scan
4702 * this scan respond to scan trigger and update cfg80211 scan database
4703 * later, scan dump command can be used to recieve scan results
4704 */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08004705int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
4706#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4707 struct net_device *dev,
4708#endif
4709 struct cfg80211_scan_request *request)
4710{
4711#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4712 struct net_device *dev = request->wdev->netdev;
4713#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304714 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07004715 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4716 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304717 hdd_config_t *cfg_param = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004718 tCsrScanRequest scanRequest;
4719 tANI_U8 *channelList = NULL, i;
4720 v_U32_t scanId = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304721 int status;
4722 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004723 v_U8_t* pP2pIe = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004724
4725 ENTER();
4726
4727 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4728 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004729
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304730 status = wlan_hdd_validate_context(pHddCtx);
4731
4732 if (0 != status)
4733 {
4734 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4735 "%s: HDD context is not valid", __func__);
4736 return status;
4737 }
4738
4739 cfg_param = pHddCtx->cfg_ini;
4740 pScanInfo = &pHddCtx->scan_info;
4741
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004742 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004743 (eConnectionState_Connecting ==
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004744 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004745 {
4746 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004747 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
4748 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004749 return -EBUSY;
4750 }
4751
Jeff Johnson295189b2012-06-20 16:38:30 -07004752#ifdef WLAN_BTAMP_FEATURE
4753 //Scan not supported when AMP traffic is on.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004754 if (VOS_TRUE == WLANBAP_AmpSessionOn())
Jeff Johnson295189b2012-06-20 16:38:30 -07004755 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004756 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004757 "%s: No scanning when AMP is on", __func__);
4758 return -EOPNOTSUPP;
4759 }
4760#endif
4761 //Scan on any other interface is not supported.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004762 if (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07004763 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004764 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004765 "%s: Not scanning on device_mode = %d",
4766 __func__, pAdapter->device_mode);
4767 return -EOPNOTSUPP;
4768 }
4769
4770 if (TRUE == pScanInfo->mScanPending)
4771 {
4772 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004773 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07004774 }
4775
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304776 //Don't Allow Scan and return busy if Remain On
Jeff Johnson32d95a32012-09-10 13:15:23 -07004777 //Channel and action frame is pending
4778 //Otherwise Cancel Remain On Channel and allow Scan
4779 //If no action frame pending
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004780 if (0 != wlan_hdd_check_remain_on_channel(pAdapter))
Jeff Johnson32d95a32012-09-10 13:15:23 -07004781 {
4782 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
4783 return -EBUSY;
4784 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004785#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004786 /* if tdls disagree scan right now, return immediately.
4787 tdls will schedule the scan when scan is allowed. (return SUCCESS)
4788 or will reject the scan if any TDLS is in progress. (return -EBUSY)
4789 */
4790 status = wlan_hdd_tdls_scan_callback (pAdapter,
4791 wiphy,
4792#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4793 dev,
Gopichand Nakkalac3c42b92013-03-20 19:42:34 -07004794#endif
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004795 request);
4796 if(status <= 0)
4797 {
4798 hddLog(VOS_TRACE_LEVEL_INFO, "%s: TDLS Pending %d", __func__, status);
4799 return status;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004800 }
4801#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07004802
Jeff Johnson295189b2012-06-20 16:38:30 -07004803 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
4804 {
4805 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08004806 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004807 return -EAGAIN;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304808 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004809 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
4810 {
4811 hddLog(VOS_TRACE_LEVEL_WARN,
4812 "%s: MAX TM Level Scan not allowed", __func__);
4813 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304814 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07004815 }
4816 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4817
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004818 /* Check if scan is allowed at this point of time.
4819 */
4820 if (!hdd_isScanAllowed(pHddCtx))
4821 {
4822 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
4823 return -EBUSY;
4824 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304825
Jeff Johnson295189b2012-06-20 16:38:30 -07004826 vos_mem_zero( &scanRequest, sizeof(scanRequest));
4827
4828 if (NULL != request)
4829 {
4830 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304831 (int)request->n_ssids);
Jeff Johnson295189b2012-06-20 16:38:30 -07004832
4833 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
4834 * Becasue of this, driver is assuming that this is not wildcard scan and so
4835 * is not aging out the scan results.
4836 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07004837 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07004838 {
4839 request->n_ssids = 0;
4840 }
4841
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004842 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07004843 {
4844 tCsrSSIDInfo *SsidInfo;
4845 int j;
4846 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
4847 /* Allocate num_ssid tCsrSSIDInfo structure */
4848 SsidInfo = scanRequest.SSIDs.SSIDList =
4849 ( tCsrSSIDInfo *)vos_mem_malloc(
4850 request->n_ssids*sizeof(tCsrSSIDInfo));
4851
4852 if(NULL == scanRequest.SSIDs.SSIDList)
4853 {
4854 hddLog(VOS_TRACE_LEVEL_ERROR,
4855 "memory alloc failed SSIDInfo buffer");
4856 return -ENOMEM;
4857 }
4858
4859 /* copy all the ssid's and their length */
4860 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
4861 {
4862 /* get the ssid length */
4863 SsidInfo->SSID.length = request->ssids[j].ssid_len;
4864 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
4865 SsidInfo->SSID.length);
4866 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
4867 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
4868 j, SsidInfo->SSID.ssId);
4869 }
4870 /* set the scan type to active */
4871 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4872 }
4873 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4874 {
4875 /* set the scan type to active */
4876 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4877 }
4878 else
4879 {
4880 /*Set the scan type to default type, in this case it is ACTIVE*/
4881 scanRequest.scanType = pScanInfo->scan_mode;
4882 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304883 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
Jeff Johnson295189b2012-06-20 16:38:30 -07004884 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4885 }
4886 else
4887 {
4888 /* set the scan type to active */
4889 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4890 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4891
4892 /* set min and max channel time to zero */
4893 scanRequest.minChnTime = 0;
4894 scanRequest.maxChnTime = 0;
4895 }
4896
4897 /* set BSSType to default type */
4898 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4899
4900 /*TODO: scan the requested channels only*/
4901
4902 /*Right now scanning all the channels */
4903 if( request )
4904 {
4905 if( request->n_channels )
4906 {
4907 channelList = vos_mem_malloc( request->n_channels );
4908 if( NULL == channelList )
4909 {
4910 status = -ENOMEM;
4911 goto free_mem;
4912 }
4913
4914 for( i = 0 ; i < request->n_channels ; i++ )
4915 channelList[i] = request->channels[i]->hw_value;
4916 }
4917
4918 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4919 scanRequest.ChannelInfo.ChannelList = channelList;
4920
4921 /* set requestType to full scan */
4922 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304923
4924 /* Flush the scan results(only p2p beacons) for STA scan and P2P
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004925 * search (Flush on both full scan and social scan but not on single
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304926 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004927 */
4928
4929 /* Supplicant does single channel scan after 8-way handshake
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304930 * and in that case driver shoudnt flush scan results. If
4931 * driver flushes the scan results here and unfortunately if
4932 * the AP doesnt respond to our probe req then association
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004933 * fails which is not desired
4934 */
4935
4936 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4937 {
4938 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4939 pAdapter->sessionId );
4940 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004941
4942 if( request->ie_len )
4943 {
4944 /* save this for future association (join requires this) */
4945 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4946 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4947 pScanInfo->scanAddIE.length = request->ie_len;
4948
4949 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004950 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4951 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004952 )
4953 {
4954 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4955 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4956 }
4957
4958 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4959 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4960
Jeff Johnson295189b2012-06-20 16:38:30 -07004961 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4962 request->ie_len);
4963 if (pP2pIe != NULL)
4964 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004965#ifdef WLAN_FEATURE_P2P_DEBUG
4966 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4967 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4968 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4969 {
4970 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4971 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4972 "Go nego completed to Connection is started");
4973 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4974 "for 8way Handshake");
4975 }
4976 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4977 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4978 {
4979 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4980 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4981 "Disconnected state to Connection is started");
4982 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4983 "for 4way Handshake");
4984 }
4985#endif
4986
Jeff Johnsone7245742012-09-05 17:12:55 -07004987 /* no_cck will be set during p2p find to disable 11b rates */
4988 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004989 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004990 hddLog(VOS_TRACE_LEVEL_INFO,
4991 "%s: This is a P2P Search", __func__);
4992 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004993
Jeff Johnsone7245742012-09-05 17:12:55 -07004994 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4995 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004996 /* set requestType to P2P Discovery */
4997 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004998 }
4999
5000 /*
5001 Skip Dfs Channel in case of P2P Search
5002 if it is set in ini file
5003 */
5004 if(cfg_param->skipDfsChnlInP2pSearch)
5005 {
5006 scanRequest.skipDfsChnlInP2pSearch = 1;
5007 }
5008 else
5009 {
5010 scanRequest.skipDfsChnlInP2pSearch = 0;
5011 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005012
Jeff Johnson295189b2012-06-20 16:38:30 -07005013 }
5014 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005015 }
5016 }
5017
5018 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
5019
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07005020 /* acquire the wakelock to avoid the apps suspend during the scan. To
5021 * address the following issues.
5022 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
5023 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
5024 * for long time, this result in apps running at full power for long time.
5025 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
5026 * be stuck in full power because of resume BMPS
5027 */
5028 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07005029
5030 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07005031 pAdapter->sessionId, &scanRequest, &scanId,
5032 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07005033
Jeff Johnson295189b2012-06-20 16:38:30 -07005034 if (eHAL_STATUS_SUCCESS != status)
5035 {
5036 hddLog(VOS_TRACE_LEVEL_ERROR,
5037 "%s: sme_ScanRequest returned error %d", __func__, status);
5038 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07005039 if(eHAL_STATUS_RESOURCES == status)
5040 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07005041 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 -07005042 status = -EBUSY;
5043 } else {
5044 status = -EIO;
5045 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07005046 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005047 goto free_mem;
5048 }
5049
5050 pScanInfo->mScanPending = TRUE;
5051 pAdapter->request = request;
5052 pScanInfo->scanId = scanId;
5053
5054 complete(&pScanInfo->scan_req_completion_event);
5055
5056free_mem:
5057 if( scanRequest.SSIDs.SSIDList )
5058 {
5059 vos_mem_free(scanRequest.SSIDs.SSIDList);
5060 }
5061
5062 if( channelList )
5063 vos_mem_free( channelList );
5064
5065 EXIT();
5066
5067 return status;
5068}
5069
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07005070
5071void hdd_select_cbmode( hdd_adapter_t *pAdapter,v_U8_t operationChannel)
5072{
5073 v_U8_t iniDot11Mode =
5074 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->dot11Mode;
5075 eHddDot11Mode hddDot11Mode = iniDot11Mode;
5076
5077 switch ( iniDot11Mode )
5078 {
5079 case eHDD_DOT11_MODE_AUTO:
5080 case eHDD_DOT11_MODE_11ac:
5081 case eHDD_DOT11_MODE_11ac_ONLY:
5082#ifdef WLAN_FEATURE_11AC
5083 hddDot11Mode = eHDD_DOT11_MODE_11ac;
5084#else
5085 hddDot11Mode = eHDD_DOT11_MODE_11n;
5086#endif
5087 break;
5088 case eHDD_DOT11_MODE_11n:
5089 case eHDD_DOT11_MODE_11n_ONLY:
5090 hddDot11Mode = eHDD_DOT11_MODE_11n;
5091 break;
5092 default:
5093 hddDot11Mode = iniDot11Mode;
5094 break;
5095 }
5096 /* This call decides required channel bonding mode */
5097 sme_SelectCBMode((WLAN_HDD_GET_CTX(pAdapter)->hHal),
5098 hdd_cfg_xlate_to_csr_phy_mode(hddDot11Mode),
5099 operationChannel);
5100}
5101
Jeff Johnson295189b2012-06-20 16:38:30 -07005102/*
5103 * FUNCTION: wlan_hdd_cfg80211_connect_start
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305104 * This function is used to start the association process
Jeff Johnson295189b2012-06-20 16:38:30 -07005105 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305106int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005107 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07005108{
5109 int status = 0;
5110 hdd_wext_state_t *pWextState;
5111 v_U32_t roamId;
5112 tCsrRoamProfile *pRoamProfile;
5113 eMib_dot11DesiredBssType connectedBssType;
5114 eCsrAuthType RSNAuthType;
5115
5116 ENTER();
5117
5118 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305119
Jeff Johnson295189b2012-06-20 16:38:30 -07005120 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
5121 {
5122 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
5123 return -EINVAL;
5124 }
5125
5126 pRoamProfile = &pWextState->roamProfile;
5127
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305128 if (pRoamProfile)
Jeff Johnson295189b2012-06-20 16:38:30 -07005129 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005130 int ret = 0;
5131 hdd_station_ctx_t *pHddStaCtx;
5132 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5133 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
5134
5135 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
5136 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
5137 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07005138 {
5139 /* Issue disconnect to CSR */
5140 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305141 if( eHAL_STATUS_SUCCESS ==
Jeff Johnson295189b2012-06-20 16:38:30 -07005142 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5143 pAdapter->sessionId,
5144 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
5145 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005146 ret = wait_for_completion_interruptible_timeout(
5147 &pAdapter->disconnect_comp_var,
5148 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5149 if (0 == ret)
5150 {
5151 VOS_ASSERT(0);
5152 }
5153 }
5154 }
5155 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
5156 {
5157 ret = wait_for_completion_interruptible_timeout(
5158 &pAdapter->disconnect_comp_var,
5159 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5160 if (0 == ret)
5161 {
5162 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005163 }
5164 }
5165
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305166 if (HDD_WMM_USER_MODE_NO_QOS ==
Jeff Johnson295189b2012-06-20 16:38:30 -07005167 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
5168 {
5169 /*QoS not enabled in cfg file*/
5170 pRoamProfile->uapsd_mask = 0;
5171 }
5172 else
5173 {
5174 /*QoS enabled, update uapsd mask from cfg file*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305175 pRoamProfile->uapsd_mask =
Jeff Johnson295189b2012-06-20 16:38:30 -07005176 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
5177 }
5178
5179 pRoamProfile->SSIDs.numOfSSIDs = 1;
5180 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
5181 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305182 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Jeff Johnson295189b2012-06-20 16:38:30 -07005183 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
5184 ssid, ssid_len);
5185
5186 if (bssid)
5187 {
5188 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
5189 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
5190 WNI_CFG_BSSID_LEN);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305191 /* Save BSSID in seperate variable as well, as RoamProfile
5192 BSSID is getting zeroed out in the association process. And in
Jeff Johnson295189b2012-06-20 16:38:30 -07005193 case of join failure we should send valid BSSID to supplicant
5194 */
5195 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
5196 WNI_CFG_BSSID_LEN);
5197 }
Dhanashri Atre51981c62013-06-13 11:47:57 -07005198 else
5199 {
5200 vos_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),WNI_CFG_BSSID_LEN);
5201 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005202
5203 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
5204 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305205 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005206 /*set gen ie*/
5207 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
5208 /*set auth*/
5209 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
5210 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005211#ifdef FEATURE_WLAN_WAPI
5212 if (pAdapter->wapi_info.nWapiMode)
5213 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005214 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005215 switch (pAdapter->wapi_info.wapiAuthMode)
5216 {
5217 case WAPI_AUTH_MODE_PSK:
5218 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005219 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07005220 pAdapter->wapi_info.wapiAuthMode);
5221 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
5222 break;
5223 }
5224 case WAPI_AUTH_MODE_CERT:
5225 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005226 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07005227 pAdapter->wapi_info.wapiAuthMode);
5228 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
5229 break;
5230 }
5231 } // End of switch
5232 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
5233 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
5234 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005235 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005236 pRoamProfile->AuthType.numEntries = 1;
5237 pRoamProfile->EncryptionType.numEntries = 1;
5238 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
5239 pRoamProfile->mcEncryptionType.numEntries = 1;
5240 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
5241 }
5242 }
5243#endif /* FEATURE_WLAN_WAPI */
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05305244#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05305245 /* Initializing gtkOffloadReqParams */
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05305246 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5247 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
5248 {
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05305249 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
5250 sizeof (tSirGtkOffloadParams));
5251 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05305252 }
5253#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005254 pRoamProfile->csrPersona = pAdapter->device_mode;
5255
Jeff Johnson32d95a32012-09-10 13:15:23 -07005256 if( operatingChannel )
5257 {
5258 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
5259 pRoamProfile->ChannelInfo.numOfChannels = 1;
5260 }
Chet Lanctot186b5732013-03-18 10:26:30 -07005261 else
5262 {
5263 pRoamProfile->ChannelInfo.ChannelList = NULL;
5264 pRoamProfile->ChannelInfo.numOfChannels = 0;
5265 }
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07005266 if ( (WLAN_HDD_IBSS == pAdapter->device_mode) && operatingChannel)
5267 {
5268 hdd_select_cbmode(pAdapter,operatingChannel);
5269 }
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005270 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
5271 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305272 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005273 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08005274 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
5275 */
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305276 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
5277 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08005278 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
5279 eConnectionState_Connecting);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305280
5281 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07005282 pAdapter->sessionId, pRoamProfile, &roamId);
5283
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305284 if ((eHAL_STATUS_SUCCESS != status) &&
5285 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
5286 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05305287
5288 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005289 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
5290 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
5291 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05305292 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005293 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05305294 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08005295
5296 pRoamProfile->ChannelInfo.ChannelList = NULL;
5297 pRoamProfile->ChannelInfo.numOfChannels = 0;
5298
Jeff Johnson295189b2012-06-20 16:38:30 -07005299 }
5300 else
5301 {
5302 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
5303 return -EINVAL;
5304 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08005305 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005306 return status;
5307}
5308
5309/*
5310 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
5311 * This function is used to set the authentication type (OPEN/SHARED).
5312 *
5313 */
5314static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
5315 enum nl80211_auth_type auth_type)
5316{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305317 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005318 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5319
5320 ENTER();
5321
5322 /*set authentication type*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305323 switch (auth_type)
Jeff Johnson295189b2012-06-20 16:38:30 -07005324 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005325 case NL80211_AUTHTYPE_AUTOMATIC:
Gopichand Nakkala29149562013-05-10 21:43:41 +05305326 hddLog(VOS_TRACE_LEVEL_INFO,
5327 "%s: set authentication type to AUTOSWITCH", __func__);
5328 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
5329 break;
5330
5331 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07005332#ifdef WLAN_FEATURE_VOWIFI_11R
5333 case NL80211_AUTHTYPE_FT:
5334#endif /* WLAN_FEATURE_VOWIFI_11R */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305335 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07005336 "%s: set authentication type to OPEN", __func__);
5337 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5338 break;
5339
5340 case NL80211_AUTHTYPE_SHARED_KEY:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305341 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07005342 "%s: set authentication type to SHARED", __func__);
5343 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
5344 break;
5345#ifdef FEATURE_WLAN_CCX
5346 case NL80211_AUTHTYPE_NETWORK_EAP:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305347 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07005348 "%s: set authentication type to CCKM WPA", __func__);
5349 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
5350 break;
5351#endif
5352
5353
5354 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305355 hddLog(VOS_TRACE_LEVEL_ERROR,
5356 "%s: Unsupported authentication type %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07005357 auth_type);
5358 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
5359 return -EINVAL;
5360 }
5361
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305362 pWextState->roamProfile.AuthType.authType[0] =
Jeff Johnson295189b2012-06-20 16:38:30 -07005363 pHddStaCtx->conn_info.authType;
5364 return 0;
5365}
5366
5367/*
5368 * FUNCTION: wlan_hdd_set_akm_suite
5369 * This function is used to set the key mgmt type(PSK/8021x).
5370 *
5371 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305372static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07005373 u32 key_mgmt
5374 )
5375{
5376 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5377 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305378
Jeff Johnson295189b2012-06-20 16:38:30 -07005379 /*set key mgmt type*/
5380 switch(key_mgmt)
5381 {
5382 case WLAN_AKM_SUITE_PSK:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05305383#ifdef WLAN_FEATURE_VOWIFI_11R
5384 case WLAN_AKM_SUITE_FT_PSK:
5385#endif
5386 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
Jeff Johnson295189b2012-06-20 16:38:30 -07005387 __func__);
5388 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
5389 break;
5390
5391 case WLAN_AKM_SUITE_8021X:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05305392#ifdef WLAN_FEATURE_VOWIFI_11R
5393 case WLAN_AKM_SUITE_FT_8021X:
5394#endif
5395 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
Jeff Johnson295189b2012-06-20 16:38:30 -07005396 __func__);
5397 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
5398 break;
5399#ifdef FEATURE_WLAN_CCX
5400#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
5401#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
5402 case WLAN_AKM_SUITE_CCKM:
5403 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
5404 __func__);
5405 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
5406 break;
5407#endif
5408
5409 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305410 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005411 __func__, key_mgmt);
5412 return -EINVAL;
5413
5414 }
5415 return 0;
5416}
5417
5418/*
5419 * FUNCTION: wlan_hdd_cfg80211_set_cipher
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305420 * This function is used to set the encryption type
Jeff Johnson295189b2012-06-20 16:38:30 -07005421 * (NONE/WEP40/WEP104/TKIP/CCMP).
5422 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305423static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
5424 u32 cipher,
Jeff Johnson295189b2012-06-20 16:38:30 -07005425 bool ucast
5426 )
5427{
5428 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305429 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005430 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5431
5432 ENTER();
5433
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305434 if (!cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07005435 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305436 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
Jeff Johnson295189b2012-06-20 16:38:30 -07005437 __func__, cipher);
5438 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5439 }
5440 else
5441 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305442
Jeff Johnson295189b2012-06-20 16:38:30 -07005443 /*set encryption method*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305444 switch (cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07005445 {
5446 case IW_AUTH_CIPHER_NONE:
5447 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5448 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305449
Jeff Johnson295189b2012-06-20 16:38:30 -07005450 case WLAN_CIPHER_SUITE_WEP40:
Gopichand Nakkala29149562013-05-10 21:43:41 +05305451 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
Jeff Johnson295189b2012-06-20 16:38:30 -07005452 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305453
Jeff Johnson295189b2012-06-20 16:38:30 -07005454 case WLAN_CIPHER_SUITE_WEP104:
Gopichand Nakkala29149562013-05-10 21:43:41 +05305455 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
Jeff Johnson295189b2012-06-20 16:38:30 -07005456 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305457
Jeff Johnson295189b2012-06-20 16:38:30 -07005458 case WLAN_CIPHER_SUITE_TKIP:
5459 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5460 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305461
Jeff Johnson295189b2012-06-20 16:38:30 -07005462 case WLAN_CIPHER_SUITE_CCMP:
5463 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5464 break;
5465#ifdef FEATURE_WLAN_WAPI
5466 case WLAN_CIPHER_SUITE_SMS4:
5467 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
5468 break;
5469#endif
5470
5471#ifdef FEATURE_WLAN_CCX
5472 case WLAN_CIPHER_SUITE_KRK:
5473 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
5474 break;
5475#endif
5476 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305477 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005478 __func__, cipher);
5479 return -EOPNOTSUPP;
5480 }
5481 }
5482
5483 if (ucast)
5484 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305485 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005486 __func__, encryptionType);
5487 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5488 pWextState->roamProfile.EncryptionType.numEntries = 1;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305489 pWextState->roamProfile.EncryptionType.encryptionType[0] =
Jeff Johnson295189b2012-06-20 16:38:30 -07005490 encryptionType;
5491 }
5492 else
5493 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305494 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005495 __func__, encryptionType);
5496 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
5497 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
5498 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
5499 }
5500
5501 return 0;
5502}
5503
5504
5505/*
5506 * FUNCTION: wlan_hdd_cfg80211_set_ie
5507 * This function is used to parse WPA/RSN IE's.
5508 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305509int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
5510 u8 *ie,
Jeff Johnson295189b2012-06-20 16:38:30 -07005511 size_t ie_len
5512 )
5513{
5514 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5515 u8 *genie = ie;
5516 v_U16_t remLen = ie_len;
5517#ifdef FEATURE_WLAN_WAPI
5518 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
5519 u16 *tmp;
5520 v_U16_t akmsuiteCount;
5521 int *akmlist;
5522#endif
5523 ENTER();
5524
5525 /* clear previous assocAddIE */
5526 pWextState->assocAddIE.length = 0;
5527 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
5528
5529 while (remLen >= 2)
5530 {
5531 v_U16_t eLen = 0;
5532 v_U8_t elementId;
5533 elementId = *genie++;
5534 eLen = *genie++;
5535 remLen -= 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305536
5537 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07005538 __func__, elementId, eLen);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305539
5540 switch ( elementId )
Jeff Johnson295189b2012-06-20 16:38:30 -07005541 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305542 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005543 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 -07005544 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305545 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005546 "%s: Invalid WPA IE", __func__);
5547 return -EINVAL;
5548 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305549 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
Jeff Johnson295189b2012-06-20 16:38:30 -07005550 {
5551 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305552 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
Jeff Johnson295189b2012-06-20 16:38:30 -07005553 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305554
Jeff Johnson295189b2012-06-20 16:38:30 -07005555 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5556 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005557 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
5558 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005559 VOS_ASSERT(0);
5560 return -ENOMEM;
5561 }
5562 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5563 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5564 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305565
Jeff Johnson295189b2012-06-20 16:38:30 -07005566 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
5567 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5568 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5569 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305570 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
5571 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005572 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
5573 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5574 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
5575 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
5576 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
5577 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305578 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
5579 P2P_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07005580 /*Consider P2P IE, only for P2P Client */
5581 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5582 {
5583 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305584 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
Jeff Johnson295189b2012-06-20 16:38:30 -07005585 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305586
Jeff Johnson295189b2012-06-20 16:38:30 -07005587 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5588 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005589 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5590 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005591 VOS_ASSERT(0);
5592 return -ENOMEM;
5593 }
5594 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5595 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5596 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305597
Jeff Johnson295189b2012-06-20 16:38:30 -07005598 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5599 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5600 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005601#ifdef WLAN_FEATURE_WFD
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305602 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
5603 WFD_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07005604 /*Consider WFD IE, only for P2P Client */
5605 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5606 {
5607 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305608 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
Jeff Johnson295189b2012-06-20 16:38:30 -07005609 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305610
Jeff Johnson295189b2012-06-20 16:38:30 -07005611 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5612 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005613 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5614 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005615 VOS_ASSERT(0);
5616 return -ENOMEM;
5617 }
5618 // WFD IE is saved to Additional IE ; it should be accumulated to handle
5619 // WPS IE + P2P IE + WFD IE
5620 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5621 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305622
Jeff Johnson295189b2012-06-20 16:38:30 -07005623 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5624 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5625 }
5626#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005627 /* Appending HS 2.0 Indication Element in Assiciation Request */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305628 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005629 HS20_OUI_TYPE_SIZE)) )
5630 {
5631 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305632 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005633 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005634
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005635 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5636 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005637 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5638 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005639 VOS_ASSERT(0);
5640 return -ENOMEM;
5641 }
5642 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5643 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005644
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005645 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5646 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5647 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005648
Praveen Kumar Sirisilla7d68b7b2013-09-22 14:01:42 -07005649 if (WLAN_HDD_IBSS == pAdapter->device_mode) {
5650
5651 /* populating as ADDIE in beacon frames */
5652 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
5653 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie - 2, eLen + 2,
5654 NULL, eANI_BOOLEAN_FALSE)== eHAL_STATUS_SUCCESS)
5655 {
5656 if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter),
5657 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
5658 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
5659 {
5660 hddLog(LOGE,
5661 "Coldn't pass "
5662 "WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
5663 }
5664 }/* ccmCfgSetStr(,WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, , )*/
5665 else
5666 hddLog(LOGE,
5667 "Could not pass on "
5668 "WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
5669
5670 /* IBSS mode doesn't contain params->proberesp_ies still
5671 beaconIE's need to be populated in probe response frames */
5672 if ( (NULL != (genie - 2)) && (0 != eLen + 2) )
5673 {
5674 u16 rem_probe_resp_ie_len = eLen + 2;
5675 u8 probe_rsp_ie_len[3] = {0};
5676 u8 counter = 0;
5677
5678 /* Check Probe Resp Length if it is greater then 255 then
5679 Store Probe Rsp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1
5680 & WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are
5681 not able Store More then 255 bytes into One Variable */
5682
5683 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
5684 {
5685 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
5686 {
5687 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
5688 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
5689 }
5690 else
5691 {
5692 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
5693 rem_probe_resp_ie_len = 0;
5694 }
5695 }
5696
5697 rem_probe_resp_ie_len = 0;
5698
5699 if (probe_rsp_ie_len[0] > 0)
5700 {
5701 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
5702 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
5703 (tANI_U8*)(genie - 2),
5704 probe_rsp_ie_len[0], NULL,
5705 eANI_BOOLEAN_FALSE)
5706 == eHAL_STATUS_FAILURE)
5707 {
5708 hddLog(LOGE,
5709 "Could not pass"
5710 "on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
5711 }
5712 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
5713 }
5714
5715 if (probe_rsp_ie_len[1] > 0)
5716 {
5717 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
5718 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
5719 (tANI_U8*)(genie - (2 + rem_probe_resp_ie_len)),
5720 probe_rsp_ie_len[1], NULL,
5721 eANI_BOOLEAN_FALSE)
5722 == eHAL_STATUS_FAILURE)
5723 {
5724 hddLog(LOGE,
5725 "Could not pass"
5726 "on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
5727 }
5728 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
5729 }
5730
5731 if (probe_rsp_ie_len[2] > 0)
5732 {
5733 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
5734 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
5735 (tANI_U8*)(genie - (2 + rem_probe_resp_ie_len)),
5736 probe_rsp_ie_len[2], NULL,
5737 eANI_BOOLEAN_FALSE)
5738 == eHAL_STATUS_FAILURE)
5739 {
5740 hddLog(LOGE,
5741 "Could not pass"
5742 "on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
5743 }
5744 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
5745 }
5746
5747 if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter),
5748 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
5749 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
5750 {
5751 hddLog(LOGE,
5752 "Could not pass"
5753 "on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
5754 }
5755 }
5756 else
5757 {
5758 // Reset WNI_CFG_PROBE_RSP Flags
5759 wlan_hdd_reset_prob_rspies(pAdapter);
5760
5761 hddLog(VOS_TRACE_LEVEL_INFO,
5762 "%s: No Probe Response IE received in set beacon",
5763 __func__);
5764 }
5765 } /* end of if (WLAN_HDD_IBSS == pAdapter->device_mode) */
Jeff Johnson295189b2012-06-20 16:38:30 -07005766 break;
5767 case DOT11F_EID_RSN:
5768 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
5769 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5770 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
5771 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
5772 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
5773 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005774 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
5775 case DOT11F_EID_EXTCAP:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305776 {
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005777 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305778 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005779 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305780
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005781 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5782 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005783 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5784 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005785 VOS_ASSERT(0);
5786 return -ENOMEM;
5787 }
5788 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5789 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305790
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005791 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5792 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5793 break;
5794 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005795#ifdef FEATURE_WLAN_WAPI
5796 case WLAN_EID_WAPI:
5797 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
5798 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
5799 pAdapter->wapi_info.nWapiMode);
5800 tmp = (u16 *)ie;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305801 tmp = tmp + 2; // Skip element Id and Len, Version
Jeff Johnson295189b2012-06-20 16:38:30 -07005802 akmsuiteCount = WPA_GET_LE16(tmp);
5803 tmp = tmp + 1;
5804 akmlist = (int *)(tmp);
5805 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
5806 {
5807 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
5808 }
5809 else
5810 {
5811 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
5812 VOS_ASSERT(0);
5813 return -EINVAL;
5814 }
5815
5816 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
5817 {
5818 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005819 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005820 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305821 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005822 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305823 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005824 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005825 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005826 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
5827 }
5828 break;
5829#endif
5830 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305831 hddLog (VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005832 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005833 /* when Unknown IE is received we should break and continue
5834 * to the next IE in the buffer instead we were returning
5835 * so changing this to break */
5836 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005837 }
5838 genie += eLen;
5839 remLen -= eLen;
5840 }
5841 EXIT();
5842 return 0;
5843}
5844
5845/*
Gopichand Nakkala18f0c262013-05-07 23:25:08 +05305846 * FUNCTION: hdd_isWPAIEPresent
5847 * Parse the received IE to find the WPA IE
5848 *
5849 */
5850static bool hdd_isWPAIEPresent(u8 *ie, u8 ie_len)
5851{
5852 v_U8_t eLen = 0;
5853 v_U16_t remLen = ie_len;
5854 v_U8_t elementId = 0;
5855
5856 while (remLen >= 2)
5857 {
5858 elementId = *ie++;
5859 eLen = *ie++;
5860 remLen -= 2;
5861 if (eLen > remLen)
5862 {
5863 hddLog(VOS_TRACE_LEVEL_ERROR,
5864 "%s: IE length is wrong %d", __func__, eLen);
5865 return FALSE;
5866 }
5867 if ((elementId == DOT11F_EID_WPA) && (remLen > 5))
5868 {
5869 /* OUI - 0x00 0X50 0XF2
5870 WPA Information Element - 0x01
5871 WPA version - 0x01*/
5872 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
5873 return TRUE;
5874 }
5875 ie += eLen;
5876 remLen -= eLen;
5877 }
5878 return FALSE;
5879}
5880
5881/*
Jeff Johnson295189b2012-06-20 16:38:30 -07005882 * FUNCTION: wlan_hdd_cfg80211_set_privacy
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305883 * This function is used to initialize the security
Jeff Johnson295189b2012-06-20 16:38:30 -07005884 * parameters during connect operation.
5885 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305886int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07005887 struct cfg80211_connect_params *req
5888 )
5889{
5890 int status = 0;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305891 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005892 ENTER();
5893
5894 /*set wpa version*/
5895 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5896
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305897 if (req->crypto.wpa_versions)
Jeff Johnson295189b2012-06-20 16:38:30 -07005898 {
Gopichand Nakkala781ded42013-06-28 12:10:45 +05305899 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
Jeff Johnson295189b2012-06-20 16:38:30 -07005900 {
5901 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5902 }
5903 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
5904 {
5905 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5906 }
5907 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305908
5909 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07005910 pWextState->wpaVersion);
5911
5912 /*set authentication type*/
5913 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
5914
5915 if (0 > status)
5916 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305917 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005918 "%s: failed to set authentication type ", __func__);
5919 return status;
5920 }
5921
5922 /*set key mgmt type*/
5923 if (req->crypto.n_akm_suites)
5924 {
5925 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
5926 if (0 > status)
5927 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305928 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
Jeff Johnson295189b2012-06-20 16:38:30 -07005929 __func__);
5930 return status;
5931 }
5932 }
5933
5934 /*set pairwise cipher type*/
5935 if (req->crypto.n_ciphers_pairwise)
5936 {
5937 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
5938 req->crypto.ciphers_pairwise[0], true);
5939 if (0 > status)
5940 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305941 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005942 "%s: failed to set unicast cipher type", __func__);
5943 return status;
5944 }
5945 }
5946 else
5947 {
5948 /*Reset previous cipher suite to none*/
5949 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
5950 if (0 > status)
5951 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305952 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005953 "%s: failed to set unicast cipher type", __func__);
5954 return status;
5955 }
5956 }
5957
5958 /*set group cipher type*/
5959 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
5960 false);
5961
5962 if (0 > status)
5963 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305964 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
Jeff Johnson295189b2012-06-20 16:38:30 -07005965 __func__);
5966 return status;
5967 }
5968
Chet Lanctot186b5732013-03-18 10:26:30 -07005969#ifdef WLAN_FEATURE_11W
5970 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
5971#endif
5972
Jeff Johnson295189b2012-06-20 16:38:30 -07005973 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
5974 if (req->ie_len)
5975 {
5976 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
5977 if ( 0 > status)
5978 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305979 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
Jeff Johnson295189b2012-06-20 16:38:30 -07005980 __func__);
5981 return status;
5982 }
5983 }
5984
5985 /*incase of WEP set default key information*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305986 if (req->key && req->key_len)
Jeff Johnson295189b2012-06-20 16:38:30 -07005987 {
5988 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
5989 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
5990 )
5991 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305992 if ( IW_AUTH_KEY_MGMT_802_1X
Jeff Johnson295189b2012-06-20 16:38:30 -07005993 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
5994 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305995 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
Jeff Johnson295189b2012-06-20 16:38:30 -07005996 __func__);
5997 return -EOPNOTSUPP;
5998 }
5999 else
6000 {
6001 u8 key_len = req->key_len;
6002 u8 key_idx = req->key_idx;
6003
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306004 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
Jeff Johnson295189b2012-06-20 16:38:30 -07006005 && (CSR_MAX_NUM_KEY > key_idx)
6006 )
6007 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306008 hddLog(VOS_TRACE_LEVEL_INFO,
6009 "%s: setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006010 __func__, key_idx, key_len);
6011 vos_mem_copy(
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306012 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07006013 req->key, key_len);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306014 pWextState->roamProfile.Keys.KeyLength[key_idx] =
Jeff Johnson295189b2012-06-20 16:38:30 -07006015 (u8)key_len;
6016 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
6017 }
6018 }
6019 }
6020 }
6021
6022 return status;
6023}
6024
6025/*
6026 * FUNCTION: wlan_hdd_cfg80211_set_privacy
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306027 * This function is used to initialize the security
Jeff Johnson295189b2012-06-20 16:38:30 -07006028 * parameters during connect operation.
6029 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306030static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006031 struct net_device *ndev,
6032 struct cfg80211_connect_params *req
6033 )
6034{
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306035 int status;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306036 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07006037 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
6038 hdd_context_t *pHddCtx = NULL;
6039
6040 ENTER();
6041
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306042 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07006043 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
6044
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306045 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6046 status = wlan_hdd_validate_context(pHddCtx);
6047
6048 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07006049 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306050 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6051 "%s: HDD context is not valid", __func__);
6052 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006053 }
6054
6055#ifdef WLAN_BTAMP_FEATURE
6056 //Infra connect not supported when AMP traffic is on.
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306057 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
Jeff Johnson295189b2012-06-20 16:38:30 -07006058 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306059 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006060 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006061 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07006062 }
6063#endif
6064 /*initialise security parameters*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306065 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
Jeff Johnson295189b2012-06-20 16:38:30 -07006066
6067 if ( 0 > status)
6068 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306069 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
Jeff Johnson295189b2012-06-20 16:38:30 -07006070 __func__);
6071 return status;
6072 }
6073
6074 //If Device Mode is Station Concurrent Sessions Exit BMps
Jeff Johnsona8a1a482012-12-12 16:49:33 -08006075 //P2P Mode will be taken care in Open/close adapter
Jeff Johnson295189b2012-06-20 16:38:30 -07006076 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
6077 (vos_concurrent_sessions_running()))
6078 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306079 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
Jeff Johnson295189b2012-06-20 16:38:30 -07006080 }
6081
Mohit Khanna765234a2012-09-11 15:08:35 -07006082 if ( req->channel )
6083 {
6084 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
6085 req->ssid_len, req->bssid,
6086 req->channel->hw_value);
6087 }
6088 else
6089 {
6090 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306091 req->ssid_len, req->bssid, 0);
Mohit Khanna765234a2012-09-11 15:08:35 -07006092 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006093
6094 if (0 > status)
6095 {
6096 //ReEnable BMPS if disabled
6097 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
6098 (NULL != pHddCtx))
6099 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306100 if (pHddCtx->hdd_wlan_suspended)
6101 {
6102 hdd_set_pwrparams(pHddCtx);
6103 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006104 //ReEnable Bmps and Imps back
6105 hdd_enable_bmps_imps(pHddCtx);
6106 }
6107
6108 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
6109 return status;
6110 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306111 pHddCtx->isAmpAllowed = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006112 EXIT();
6113 return status;
6114}
6115
6116
6117/*
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306118 * FUNCTION: wlan_hdd_disconnect
6119 * This function is used to issue a disconnect request to SME
6120 */
6121int wlan_hdd_disconnect( hdd_adapter_t *pAdapter, u16 reason )
6122{
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306123 int status;
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306124 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306125 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6126
6127 status = wlan_hdd_validate_context(pHddCtx);
6128
6129 if (0 != status)
6130 {
6131 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6132 "%s: HDD context is not valid", __func__);
6133 return status;
6134 }
6135
6136 pHddCtx->isAmpAllowed = VOS_TRUE;
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306137 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306138 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306139
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306140 /*issue disconnect*/
6141 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
6142 pAdapter->sessionId, reason);
6143
6144 if ( 0 != status )
6145 {
6146 hddLog(VOS_TRACE_LEVEL_ERROR,
6147 "%s csrRoamDisconnect failure, returned %d \n",
6148 __func__, (int)status );
6149 return -EINVAL;
6150 }
6151 wait_for_completion_interruptible_timeout(
6152 &pAdapter->disconnect_comp_var,
6153 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6154 /*stop tx queues*/
6155 netif_tx_disable(pAdapter->dev);
6156 netif_carrier_off(pAdapter->dev);
6157 return status;
6158}
6159
6160
6161/*
Jeff Johnson295189b2012-06-20 16:38:30 -07006162 * FUNCTION: wlan_hdd_cfg80211_disconnect
6163 * This function is used to issue a disconnect request to SME
6164 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306165static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006166 struct net_device *dev,
6167 u16 reason
6168 )
6169{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306170 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
6171 tCsrRoamProfile *pRoamProfile =
Jeff Johnson295189b2012-06-20 16:38:30 -07006172 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306173 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006174 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006175 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05306176#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006177 tANI_U8 staIdx;
6178#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306179
Jeff Johnson295189b2012-06-20 16:38:30 -07006180 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306181
6182 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07006183 __func__,pAdapter->device_mode);
6184
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306185 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
6186 __func__, reason);
Jeff Johnson295189b2012-06-20 16:38:30 -07006187
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306188 status = wlan_hdd_validate_context(pHddCtx);
6189
6190 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07006191 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306192 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6193 "%s: HDD context is not valid", __func__);
6194 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006195 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306196
Jeff Johnson295189b2012-06-20 16:38:30 -07006197 if (NULL != pRoamProfile)
6198 {
6199 /*issue disconnect request to SME, if station is in connected state*/
6200 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
6201 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306202 eCsrRoamDisconnectReason reasonCode =
Jeff Johnson295189b2012-06-20 16:38:30 -07006203 eCSR_DISCONNECT_REASON_UNSPECIFIED;
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05306204 hdd_scaninfo_t *pScanInfo;
Jeff Johnson295189b2012-06-20 16:38:30 -07006205 switch(reason)
6206 {
6207 case WLAN_REASON_MIC_FAILURE:
6208 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
6209 break;
6210
6211 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
6212 case WLAN_REASON_DISASSOC_AP_BUSY:
6213 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
6214 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
6215 break;
6216
6217 case WLAN_REASON_PREV_AUTH_NOT_VALID:
6218 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
6219 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
6220 break;
6221
6222 case WLAN_REASON_DEAUTH_LEAVING:
6223 default:
6224 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
6225 break;
6226 }
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05306227 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6228 pScanInfo = &pHddCtx->scan_info;
6229 if (pScanInfo->mScanPending)
6230 {
6231 hddLog(VOS_TRACE_LEVEL_INFO, "Disconnect is in progress, "
6232 "Aborting Scan");
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05306233 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05306234 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006235
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006236#ifdef FEATURE_WLAN_TDLS
6237 /* First clean up the tdls peers if any */
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006238 for (staIdx = 0 ; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006239 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006240 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId == pAdapter->sessionId) &&
6241 (pHddCtx->tdlsConnInfo[staIdx].staId))
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006242 {
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006243 uint8 *mac;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006244 mac = pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006245 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006246 "%s: call sme_DeleteTdlsPeerSta staId %d sessionId %d " MAC_ADDRESS_STR,
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006247 __func__, pHddCtx->tdlsConnInfo[staIdx].staId, pAdapter->sessionId,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006248 MAC_ADDR_ARRAY(mac));
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006249 sme_DeleteTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006250 pAdapter->sessionId,
6251 mac);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006252 }
6253 }
6254#endif
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306255 status = wlan_hdd_disconnect(pAdapter, reasonCode);
6256 if ( 0 != status )
Jeff Johnson295189b2012-06-20 16:38:30 -07006257 {
6258 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306259 "%s wlan_hdd_disconnect failure, returned %d \n",
Jeff Johnson295189b2012-06-20 16:38:30 -07006260 __func__, (int)status );
6261 return -EINVAL;
6262 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006263 }
6264 }
6265 else
6266 {
6267 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
6268 }
6269
6270 return status;
6271}
6272
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306273
Jeff Johnson295189b2012-06-20 16:38:30 -07006274/*
6275 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306276 * This function is used to initialize the security
Jeff Johnson295189b2012-06-20 16:38:30 -07006277 * settings in IBSS mode.
6278 */
6279static int wlan_hdd_cfg80211_set_privacy_ibss(
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306280 hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07006281 struct cfg80211_ibss_params *params
6282 )
6283{
6284 int status = 0;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306285 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006286 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
6287 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306288
Jeff Johnson295189b2012-06-20 16:38:30 -07006289 ENTER();
6290
6291 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
6292
6293 if (params->ie_len && ( NULL != params->ie) )
6294 {
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006295 if (wlan_hdd_cfg80211_get_ie_ptr (params->ie,
6296 params->ie_len, WLAN_EID_RSN ))
Jeff Johnson295189b2012-06-20 16:38:30 -07006297 {
6298 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
6299 encryptionType = eCSR_ENCRYPT_TYPE_AES;
6300 }
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006301 else if ( hdd_isWPAIEPresent (params->ie, params->ie_len ))
Jeff Johnson295189b2012-06-20 16:38:30 -07006302 {
Shailender Karmuchi642e9812013-05-30 14:34:49 -07006303 tDot11fIEWPA dot11WPAIE;
6304 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006305 u8 *ie;
Shailender Karmuchi642e9812013-05-30 14:34:49 -07006306
Wilson Yang00256342013-10-10 23:13:38 -07006307 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006308 ie = wlan_hdd_cfg80211_get_ie_ptr (params->ie,
6309 params->ie_len, DOT11F_EID_WPA);
6310 if ( NULL != ie )
6311 {
6312 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
6313 // Unpack the WPA IE
6314 //Skip past the EID byte and length byte - and four byte WiFi OUI
6315 dot11fUnpackIeWPA((tpAniSirGlobal) halHandle,
6316 &ie[2+4],
6317 ie[1] - 4,
6318 &dot11WPAIE);
6319 /*Extract the multicast cipher, the encType for unicast
6320 cipher for wpa-none is none*/
6321 encryptionType =
6322 hdd_TranslateWPAToCsrEncryptionType(dot11WPAIE.multicast_cipher);
6323 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006324 }
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006325
Jeff Johnson295189b2012-06-20 16:38:30 -07006326 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
6327
6328 if (0 > status)
6329 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306330 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
Jeff Johnson295189b2012-06-20 16:38:30 -07006331 __func__);
6332 return status;
6333 }
6334 }
6335
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306336 pWextState->roamProfile.AuthType.authType[0] =
6337 pHddStaCtx->conn_info.authType =
Jeff Johnson295189b2012-06-20 16:38:30 -07006338 eCSR_AUTH_TYPE_OPEN_SYSTEM;
6339
6340 if (params->privacy)
6341 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306342 /* Security enabled IBSS, At this time there is no information available
6343 * about the security paramters, so initialise the encryption type to
Jeff Johnson295189b2012-06-20 16:38:30 -07006344 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306345 * The correct security parameters will be updated later in
Jeff Johnson295189b2012-06-20 16:38:30 -07006346 * wlan_hdd_cfg80211_add_key */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306347 /* Hal expects encryption type to be set inorder
Jeff Johnson295189b2012-06-20 16:38:30 -07006348 *enable privacy bit in beacons */
6349
6350 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
6351 }
Shailender Karmuchi642e9812013-05-30 14:34:49 -07006352 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
6353 "encryptionType=%d", encryptionType);
Jeff Johnson295189b2012-06-20 16:38:30 -07006354 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
6355 pWextState->roamProfile.EncryptionType.numEntries = 1;
6356 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
Jeff Johnson295189b2012-06-20 16:38:30 -07006357 return status;
6358}
6359
6360/*
6361 * FUNCTION: wlan_hdd_cfg80211_join_ibss
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306362 * This function is used to create/join an IBSS
Jeff Johnson295189b2012-06-20 16:38:30 -07006363 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306364static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006365 struct net_device *dev,
6366 struct cfg80211_ibss_params *params
6367 )
6368{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306369 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07006370 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6371 tCsrRoamProfile *pRoamProfile;
6372 int status;
6373 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306374 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006375
6376 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306377
6378 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07006379 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
6380
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306381 status = wlan_hdd_validate_context(pHddCtx);
6382
6383 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07006384 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306385 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6386 "%s: HDD context is not valid", __func__);
6387 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006388 }
6389
6390 if (NULL == pWextState)
6391 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306392 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07006393 __func__);
6394 return -EIO;
6395 }
6396
6397 pRoamProfile = &pWextState->roamProfile;
6398
6399 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
6400 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306401 hddLog (VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006402 "%s Interface type is not set to IBSS \n", __func__);
6403 return -EINVAL;
6404 }
6405
6406 /* Set Channel */
Yue Maf49ba872013-08-19 12:04:25 -07006407 if (NULL !=
6408#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
6409 params->chandef.chan)
6410#else
6411 params->channel)
6412#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006413 {
6414 u8 channelNum;
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006415 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6416 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
6417 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
6418 int indx;
Jeff Johnson295189b2012-06-20 16:38:30 -07006419
6420 /* Get channel number */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306421 channelNum =
Yue Maf49ba872013-08-19 12:04:25 -07006422 ieee80211_frequency_to_channel(
6423#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
6424 params->chandef.chan->center_freq);
6425#else
6426 params->channel->center_freq);
6427#endif
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006428
6429 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
6430 validChan, &numChans))
Jeff Johnson295189b2012-06-20 16:38:30 -07006431 {
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006432 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
6433 __func__);
6434 return -EOPNOTSUPP;
Jeff Johnson295189b2012-06-20 16:38:30 -07006435 }
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006436
6437 for (indx = 0; indx < numChans; indx++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006438 {
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006439 if (channelNum == validChan[indx])
6440 {
6441 break;
6442 }
6443 }
6444 if (indx >= numChans)
6445 {
6446 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07006447 __func__, channelNum);
6448 return -EINVAL;
6449 }
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006450 /* Set the Operational Channel */
6451 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
6452 channelNum);
6453 pRoamProfile->ChannelInfo.numOfChannels = 1;
6454 pHddStaCtx->conn_info.operationChannel = channelNum;
6455 pRoamProfile->ChannelInfo.ChannelList =
6456 &pHddStaCtx->conn_info.operationChannel;
Jeff Johnson295189b2012-06-20 16:38:30 -07006457 }
6458
6459 /* Initialize security parameters */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306460 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
Jeff Johnson295189b2012-06-20 16:38:30 -07006461 if (status < 0)
6462 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306463 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
Jeff Johnson295189b2012-06-20 16:38:30 -07006464 __func__);
6465 return status;
6466 }
6467
6468 /* Issue connect start */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306469 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006470 params->ssid_len, params->bssid,
6471 pHddStaCtx->conn_info.operationChannel);
Jeff Johnson295189b2012-06-20 16:38:30 -07006472
6473 if (0 > status)
6474 {
6475 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
6476 return status;
6477 }
6478
6479 return 0;
6480}
6481
6482/*
6483 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306484 * This function is used to leave an IBSS
Jeff Johnson295189b2012-06-20 16:38:30 -07006485 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306486static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006487 struct net_device *dev
6488 )
6489{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306490 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07006491 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6492 tCsrRoamProfile *pRoamProfile;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306493 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6494 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006495
6496 ENTER();
6497
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306498 status = wlan_hdd_validate_context(pHddCtx);
6499
6500 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006501 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306502 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6503 "%s: HDD context is not valid", __func__);
6504 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006505 }
6506
Jeff Johnson295189b2012-06-20 16:38:30 -07006507 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
6508 if (NULL == pWextState)
6509 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306510 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07006511 __func__);
6512 return -EIO;
6513 }
6514
6515 pRoamProfile = &pWextState->roamProfile;
6516
6517 /* Issue disconnect only if interface type is set to IBSS */
6518 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
6519 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306520 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
Jeff Johnson295189b2012-06-20 16:38:30 -07006521 __func__);
6522 return -EINVAL;
6523 }
6524
6525 /* Issue Disconnect request */
6526 INIT_COMPLETION(pAdapter->disconnect_comp_var);
6527 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6528 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6529
6530 return 0;
6531}
6532
6533/*
6534 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
6535 * This function is used to set the phy parameters
6536 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
6537 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306538static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006539 u32 changed)
6540{
6541 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6542 tHalHandle hHal = pHddCtx->hHal;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306543 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006544
6545 ENTER();
6546
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306547 status = wlan_hdd_validate_context(pHddCtx);
6548
6549 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006550 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306551 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6552 "%s: HDD context is not valid", __func__);
6553 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006554 }
6555
Jeff Johnson295189b2012-06-20 16:38:30 -07006556 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
6557 {
6558 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
6559 WNI_CFG_RTS_THRESHOLD_STAMAX :
6560 wiphy->rts_threshold;
6561
6562 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306563 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
Jeff Johnson295189b2012-06-20 16:38:30 -07006564 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306565 hddLog(VOS_TRACE_LEVEL_ERROR,
6566 "%s: Invalid RTS Threshold value %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006567 __func__, rts_threshold);
6568 return -EINVAL;
6569 }
6570
6571 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
6572 rts_threshold, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306573 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07006574 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306575 hddLog(VOS_TRACE_LEVEL_ERROR,
6576 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006577 __func__, rts_threshold);
6578 return -EIO;
6579 }
6580
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306581 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07006582 rts_threshold);
6583 }
6584
6585 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
6586 {
6587 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
6588 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
6589 wiphy->frag_threshold;
6590
6591 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306592 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
Jeff Johnson295189b2012-06-20 16:38:30 -07006593 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306594 hddLog(VOS_TRACE_LEVEL_ERROR,
6595 "%s: Invalid frag_threshold value %hu", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07006596 frag_threshold);
6597 return -EINVAL;
6598 }
6599
6600 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
6601 frag_threshold, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306602 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07006603 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306604 hddLog(VOS_TRACE_LEVEL_ERROR,
6605 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006606 __func__, frag_threshold);
6607 return -EIO;
6608 }
6609
6610 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
6611 frag_threshold);
6612 }
6613
6614 if ((changed & WIPHY_PARAM_RETRY_SHORT)
6615 || (changed & WIPHY_PARAM_RETRY_LONG))
6616 {
6617 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
6618 wiphy->retry_short :
6619 wiphy->retry_long;
6620
6621 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
6622 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
6623 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306624 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006625 __func__, retry_value);
6626 return -EINVAL;
6627 }
6628
6629 if (changed & WIPHY_PARAM_RETRY_SHORT)
6630 {
6631 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
6632 retry_value, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306633 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07006634 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306635 hddLog(VOS_TRACE_LEVEL_ERROR,
6636 "%s: ccmCfgSetInt failed for long retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006637 __func__, retry_value);
6638 return -EIO;
6639 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306640 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006641 __func__, retry_value);
6642 }
6643 else if (changed & WIPHY_PARAM_RETRY_SHORT)
6644 {
6645 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
6646 retry_value, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306647 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07006648 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306649 hddLog(VOS_TRACE_LEVEL_ERROR,
6650 "%s: ccmCfgSetInt failed for short retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006651 __func__, retry_value);
6652 return -EIO;
6653 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306654 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006655 __func__, retry_value);
6656 }
6657 }
6658
6659 return 0;
6660}
6661
6662/*
6663 * FUNCTION: wlan_hdd_cfg80211_set_txpower
6664 * This function is used to set the txpower
6665 */
6666static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
Yue Maf49ba872013-08-19 12:04:25 -07006667#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
6668 struct wireless_dev *wdev,
6669#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006670#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306671 enum tx_power_setting type,
Jeff Johnson295189b2012-06-20 16:38:30 -07006672#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306673 enum nl80211_tx_power_setting type,
Jeff Johnson295189b2012-06-20 16:38:30 -07006674#endif
6675 int dbm)
6676{
6677 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306678 tHalHandle hHal = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006679 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
6680 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306681 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006682
6683 ENTER();
6684
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306685 status = wlan_hdd_validate_context(pHddCtx);
6686
6687 if (0 != status)
6688 {
6689 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6690 "%s: HDD context is not valid", __func__);
6691 return status;
6692 }
6693
6694 hHal = pHddCtx->hHal;
6695
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306696 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
6697 dbm, ccmCfgSetCallback,
6698 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07006699 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306700 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006701 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
6702 return -EIO;
6703 }
6704
6705 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
6706 dbm);
6707
6708 switch(type)
6709 {
6710 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
6711 /* Fall through */
6712 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
6713 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
6714 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306715 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
6716 __func__);
6717 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006718 }
6719 break;
6720 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306721 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
Jeff Johnson295189b2012-06-20 16:38:30 -07006722 __func__);
6723 return -EOPNOTSUPP;
6724 break;
6725 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306726 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
6727 __func__, type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006728 return -EIO;
6729 }
6730
6731 return 0;
6732}
6733
6734/*
6735 * FUNCTION: wlan_hdd_cfg80211_get_txpower
6736 * This function is used to read the txpower
6737 */
Yue Maf49ba872013-08-19 12:04:25 -07006738static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy,
6739#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
6740 struct wireless_dev *wdev,
6741#endif
6742 int *dbm)
Jeff Johnson295189b2012-06-20 16:38:30 -07006743{
6744
6745 hdd_adapter_t *pAdapter;
6746 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306747 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006748
Jeff Johnsone7245742012-09-05 17:12:55 -07006749 ENTER();
6750
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306751 status = wlan_hdd_validate_context(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006752
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306753 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006754 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306755 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6756 "%s: HDD context is not valid", __func__);
6757 *dbm = 0;
6758 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006759 }
6760
Jeff Johnson295189b2012-06-20 16:38:30 -07006761 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
6762 if (NULL == pAdapter)
6763 {
6764 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
6765 return -ENOENT;
6766 }
6767
6768 wlan_hdd_get_classAstats(pAdapter);
6769 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
6770
Jeff Johnsone7245742012-09-05 17:12:55 -07006771 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006772 return 0;
6773}
6774
6775static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
6776 u8* mac, struct station_info *sinfo)
6777{
6778 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
6779 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6780 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
6781 tANI_U8 rate_flags;
6782
6783 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6784 hdd_config_t *pCfg = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07006785
6786 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
6787 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
6788 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
6789 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
6790 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
6791 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
6792 tANI_U16 maxRate = 0;
6793 tANI_U16 myRate;
6794 tANI_U16 currentRate = 0;
6795 tANI_U8 maxSpeedMCS = 0;
6796 tANI_U8 maxMCSIdx = 0;
6797 tANI_U8 rateFlag = 1;
6798 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006799 tANI_U16 temp;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306800 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006801
Leo Chang6f8870f2013-03-26 18:11:36 -07006802#ifdef WLAN_FEATURE_11AC
6803 tANI_U32 vht_mcs_map;
6804 eDataRate11ACMaxMcs vhtMaxMcs;
6805#endif /* WLAN_FEATURE_11AC */
6806
Jeff Johnsone7245742012-09-05 17:12:55 -07006807 ENTER();
6808
Jeff Johnson295189b2012-06-20 16:38:30 -07006809 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
6810 (0 == ssidlen))
6811 {
6812 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
6813 " Invalid ssidlen, %d", __func__, ssidlen);
6814 /*To keep GUI happy*/
6815 return 0;
6816 }
6817
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306818 status = wlan_hdd_validate_context(pHddCtx);
6819
6820 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006821 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306822 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6823 "%s: HDD context is not valid", __func__);
6824 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006825 }
6826
Jeff Johnson295189b2012-06-20 16:38:30 -07006827 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
6828 sinfo->filled |= STATION_INFO_SIGNAL;
6829
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006830 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006831 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
6832
6833 //convert to the UI units of 100kbps
6834 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
6835
6836#ifdef LINKSPEED_DEBUG_ENABLED
Leo Chang6f8870f2013-03-26 18:11:36 -07006837 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 -07006838 sinfo->signal,
6839 pCfg->reportMaxLinkSpeed,
6840 myRate,
6841 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006842 (int) pCfg->linkSpeedRssiMid,
6843 (int) pCfg->linkSpeedRssiLow,
Leo Chang6f8870f2013-03-26 18:11:36 -07006844 (int) rate_flags,
6845 (int) pAdapter->hdd_stats.ClassA_stat.mcs_index);
Jeff Johnson295189b2012-06-20 16:38:30 -07006846#endif //LINKSPEED_DEBUG_ENABLED
6847
6848 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
6849 {
6850 // we do not want to necessarily report the current speed
6851 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
6852 {
6853 // report the max possible speed
6854 rssidx = 0;
6855 }
6856 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
6857 {
6858 // report the max possible speed with RSSI scaling
6859 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
6860 {
6861 // report the max possible speed
6862 rssidx = 0;
6863 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006864 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07006865 {
6866 // report middle speed
6867 rssidx = 1;
6868 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006869 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
6870 {
6871 // report middle speed
6872 rssidx = 2;
6873 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006874 else
6875 {
6876 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006877 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07006878 }
6879 }
6880 else
6881 {
6882 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
6883 hddLog(VOS_TRACE_LEVEL_ERROR,
6884 "%s: Invalid value for reportMaxLinkSpeed: %u",
6885 __func__, pCfg->reportMaxLinkSpeed);
6886 rssidx = 0;
6887 }
6888
6889 maxRate = 0;
6890
6891 /* Get Basic Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306892 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_OPERATIONAL_RATE_SET,
6893 OperationalRates, &ORLeng))
6894 {
6895 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6896 /*To keep GUI happy*/
6897 return 0;
6898 }
6899
Jeff Johnson295189b2012-06-20 16:38:30 -07006900 for (i = 0; i < ORLeng; i++)
6901 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006902 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006903 {
6904 /* Validate Rate Set */
6905 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
6906 {
6907 currentRate = supported_data_rate[j].supported_rate[rssidx];
6908 break;
6909 }
6910 }
6911 /* Update MAX rate */
6912 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6913 }
6914
6915 /* Get Extended Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306916 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
6917 ExtendedRates, &ERLeng))
6918 {
6919 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6920 /*To keep GUI happy*/
6921 return 0;
6922 }
6923
Jeff Johnson295189b2012-06-20 16:38:30 -07006924 for (i = 0; i < ERLeng; i++)
6925 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006926 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006927 {
6928 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
6929 {
6930 currentRate = supported_data_rate[j].supported_rate[rssidx];
6931 break;
6932 }
6933 }
6934 /* Update MAX rate */
6935 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6936 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006937 /* Get MCS Rate Set -- but only if we are connected at MCS
6938 rates or if we are always reporting max speed or if we have
6939 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006940 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07006941 {
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306942 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_CURRENT_MCS_SET,
6943 MCSRates, &MCSLeng))
6944 {
6945 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6946 /*To keep GUI happy*/
6947 return 0;
6948 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006949 rateFlag = 0;
Leo Chang6f8870f2013-03-26 18:11:36 -07006950#ifdef WLAN_FEATURE_11AC
6951 /* VHT80 rate has seperate rate table */
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306952 if (rate_flags & (eHAL_TX_RATE_VHT20|eHAL_TX_RATE_VHT40|eHAL_TX_RATE_VHT80))
Jeff Johnson295189b2012-06-20 16:38:30 -07006953 {
Leo Chang6f8870f2013-03-26 18:11:36 -07006954 ccmCfgGetInt(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_VHT_TX_MCS_MAP, &vht_mcs_map);
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306955 vhtMaxMcs = (eDataRate11ACMaxMcs)(vht_mcs_map & DATA_RATE_11AC_MCS_MASK );
Leo Chang6f8870f2013-03-26 18:11:36 -07006956 if (rate_flags & eHAL_TX_RATE_SGI)
Jeff Johnson295189b2012-06-20 16:38:30 -07006957 {
Leo Chang6f8870f2013-03-26 18:11:36 -07006958 rateFlag |= 1;
Jeff Johnson295189b2012-06-20 16:38:30 -07006959 }
Leo Chang6f8870f2013-03-26 18:11:36 -07006960 if (DATA_RATE_11AC_MAX_MCS_7 == vhtMaxMcs)
Jeff Johnson295189b2012-06-20 16:38:30 -07006961 {
Leo Chang6f8870f2013-03-26 18:11:36 -07006962 maxMCSIdx = 7;
6963 }
6964 else if (DATA_RATE_11AC_MAX_MCS_8 == vhtMaxMcs)
6965 {
6966 maxMCSIdx = 8;
6967 }
6968 else if (DATA_RATE_11AC_MAX_MCS_9 == vhtMaxMcs)
6969 {
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306970 //VHT20 is supporting 0~8
6971 if (rate_flags & eHAL_TX_RATE_VHT20)
6972 maxMCSIdx = 8;
6973 else
6974 maxMCSIdx = 9;
Leo Chang6f8870f2013-03-26 18:11:36 -07006975 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306976
6977 if (rate_flags & eHAL_TX_RATE_VHT80)
6978 {
6979 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT80_rate[rateFlag];
6980 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT80_rate[rateFlag];
6981 }
6982 else if (rate_flags & eHAL_TX_RATE_VHT40)
6983 {
6984 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT40_rate[rateFlag];
6985 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT40_rate[rateFlag];
6986 }
6987 else if (rate_flags & eHAL_TX_RATE_VHT20)
6988 {
6989 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT20_rate[rateFlag];
6990 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT20_rate[rateFlag];
6991 }
6992
Leo Chang6f8870f2013-03-26 18:11:36 -07006993 maxSpeedMCS = 1;
6994 if (currentRate > maxRate)
6995 {
6996 maxRate = currentRate;
6997 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306998
Leo Chang6f8870f2013-03-26 18:11:36 -07006999 }
7000 else
7001#endif /* WLAN_FEATURE_11AC */
7002 {
7003 if (rate_flags & eHAL_TX_RATE_HT40)
7004 {
7005 rateFlag |= 1;
7006 }
7007 if (rate_flags & eHAL_TX_RATE_SGI)
7008 {
7009 rateFlag |= 2;
7010 }
7011
7012 for (i = 0; i < MCSLeng; i++)
7013 {
7014 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
7015 for (j = 0; j < temp; j++)
7016 {
7017 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
7018 {
7019 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
7020 break;
7021 }
7022 }
7023 if ((j < temp) && (currentRate > maxRate))
7024 {
7025 maxRate = currentRate;
7026 maxSpeedMCS = 1;
7027 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
7028 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007029 }
7030 }
7031 }
7032
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307033 else if (!(rate_flags & eHAL_TX_RATE_LEGACY))
7034 {
7035 maxRate = myRate;
7036 maxSpeedMCS = 1;
7037 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
7038 }
7039
Jeff Johnson295189b2012-06-20 16:38:30 -07007040 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07007041 if (((maxRate < myRate) && (0 == rssidx)) ||
7042 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07007043 {
7044 maxRate = myRate;
7045 if (rate_flags & eHAL_TX_RATE_LEGACY)
7046 {
7047 maxSpeedMCS = 0;
7048 }
7049 else
7050 {
7051 maxSpeedMCS = 1;
7052 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
7053 }
7054 }
7055
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307056 if (rate_flags & eHAL_TX_RATE_LEGACY)
Jeff Johnson295189b2012-06-20 16:38:30 -07007057 {
7058 sinfo->txrate.legacy = maxRate;
7059#ifdef LINKSPEED_DEBUG_ENABLED
7060 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
7061#endif //LINKSPEED_DEBUG_ENABLED
7062 }
7063 else
7064 {
7065 sinfo->txrate.mcs = maxMCSIdx;
Leo Chang6f8870f2013-03-26 18:11:36 -07007066#ifdef WLAN_FEATURE_11AC
7067 sinfo->txrate.nss = 1;
7068 if (rate_flags & eHAL_TX_RATE_VHT80)
7069 {
7070 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307071 sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Leo Chang6f8870f2013-03-26 18:11:36 -07007072 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307073 else if (rate_flags & eHAL_TX_RATE_VHT40)
Leo Chang6f8870f2013-03-26 18:11:36 -07007074 {
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307075 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
7076 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
7077 }
7078 else if (rate_flags & eHAL_TX_RATE_VHT20)
7079 {
7080 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
7081 }
7082#endif /* WLAN_FEATURE_11AC */
7083 if (rate_flags & (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40))
7084 {
7085 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
7086 if (rate_flags & eHAL_TX_RATE_HT40)
7087 {
7088 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
7089 }
Leo Chang6f8870f2013-03-26 18:11:36 -07007090 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007091 if (rate_flags & eHAL_TX_RATE_SGI)
7092 {
7093 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
7094 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307095
Jeff Johnson295189b2012-06-20 16:38:30 -07007096#ifdef LINKSPEED_DEBUG_ENABLED
7097 pr_info("Reporting MCS rate %d flags %x\n",
7098 sinfo->txrate.mcs,
7099 sinfo->txrate.flags );
7100#endif //LINKSPEED_DEBUG_ENABLED
7101 }
7102 }
7103 else
7104 {
7105 // report current rate instead of max rate
7106
7107 if (rate_flags & eHAL_TX_RATE_LEGACY)
7108 {
7109 //provide to the UI in units of 100kbps
7110 sinfo->txrate.legacy = myRate;
7111#ifdef LINKSPEED_DEBUG_ENABLED
7112 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
7113#endif //LINKSPEED_DEBUG_ENABLED
7114 }
7115 else
7116 {
7117 //must be MCS
7118 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
Leo Chang6f8870f2013-03-26 18:11:36 -07007119#ifdef WLAN_FEATURE_11AC
7120 sinfo->txrate.nss = 1;
7121 if (rate_flags & eHAL_TX_RATE_VHT80)
7122 {
7123 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
7124 }
7125 else
7126#endif /* WLAN_FEATURE_11AC */
7127 {
7128 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
7129 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007130 if (rate_flags & eHAL_TX_RATE_SGI)
7131 {
7132 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
7133 }
7134 if (rate_flags & eHAL_TX_RATE_HT40)
7135 {
7136 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
7137 }
Leo Chang6f8870f2013-03-26 18:11:36 -07007138#ifdef WLAN_FEATURE_11AC
7139 else if (rate_flags & eHAL_TX_RATE_VHT80)
7140 {
7141 sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
7142 }
7143#endif /* WLAN_FEATURE_11AC */
Jeff Johnson295189b2012-06-20 16:38:30 -07007144#ifdef LINKSPEED_DEBUG_ENABLED
7145 pr_info("Reporting actual MCS rate %d flags %x\n",
7146 sinfo->txrate.mcs,
7147 sinfo->txrate.flags );
7148#endif //LINKSPEED_DEBUG_ENABLED
7149 }
7150 }
7151 sinfo->filled |= STATION_INFO_TX_BITRATE;
7152
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07007153 sinfo->tx_packets =
7154 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
7155 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
7156 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
7157 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
7158
7159 sinfo->tx_retries =
7160 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
7161 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
7162 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
7163 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
7164
7165 sinfo->tx_failed =
7166 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
7167 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
7168 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
7169 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
7170
7171 sinfo->filled |=
7172 STATION_INFO_TX_PACKETS |
7173 STATION_INFO_TX_RETRIES |
7174 STATION_INFO_TX_FAILED;
7175
7176 EXIT();
7177 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007178}
7179
7180static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
Sameer Thalappilc9f26e92013-06-07 10:11:06 -07007181 struct net_device *dev, bool mode, int timeout)
Jeff Johnson295189b2012-06-20 16:38:30 -07007182{
7183 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05307184 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07007185 VOS_STATUS vos_status;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307186 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07007187
Jeff Johnsone7245742012-09-05 17:12:55 -07007188 ENTER();
7189
Jeff Johnson295189b2012-06-20 16:38:30 -07007190 if (NULL == pAdapter)
7191 {
7192 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
7193 return -ENODEV;
7194 }
7195
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05307196 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307197 status = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05307198
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307199 if (0 != status)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307200 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307201 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7202 "%s: HDD context is not valid", __func__);
7203 return status;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307204 }
7205
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05307206 if ((DRIVER_POWER_MODE_AUTO == !mode) &&
7207 (TRUE == pHddCtx->hdd_wlan_suspended) &&
7208 (pHddCtx->cfg_ini->fhostArpOffload) &&
7209 (eConnectionState_Associated ==
7210 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
7211 {
Amar Singhald53568e2013-09-26 11:03:45 -07007212
7213 hddLog(VOS_TRACE_LEVEL_INFO,
7214 "offload: in cfg80211_set_power_mgmt, calling arp offload");
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05307215 vos_status = hdd_conf_arp_offload(pAdapter, TRUE);
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05307216 if (!VOS_IS_STATUS_SUCCESS(vos_status))
7217 {
7218 hddLog(VOS_TRACE_LEVEL_INFO,
7219 "%s:Failed to enable ARPOFFLOAD Feature %d\n",
7220 __func__, vos_status);
7221 }
7222 }
7223
Jeff Johnson295189b2012-06-20 16:38:30 -07007224 /**The get power cmd from the supplicant gets updated by the nl only
7225 *on successful execution of the function call
7226 *we are oppositely mapped w.r.t mode in the driver
7227 **/
7228 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
7229
Jeff Johnsone7245742012-09-05 17:12:55 -07007230 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07007231 if (VOS_STATUS_E_FAILURE == vos_status)
7232 {
7233 return -EINVAL;
7234 }
7235 return 0;
7236}
7237
7238
7239#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7240static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
7241 struct net_device *netdev,
7242 u8 key_index)
7243{
Jeff Johnsone7245742012-09-05 17:12:55 -07007244 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007245 return 0;
7246}
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307247#endif //LINUX_VERSION_CODE
Jeff Johnson295189b2012-06-20 16:38:30 -07007248
7249#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
7250static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
7251 struct net_device *dev,
7252 struct ieee80211_txq_params *params)
7253{
Jeff Johnsone7245742012-09-05 17:12:55 -07007254 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007255 return 0;
7256}
7257#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7258static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
7259 struct ieee80211_txq_params *params)
7260{
Jeff Johnsone7245742012-09-05 17:12:55 -07007261 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007262 return 0;
7263}
7264#endif //LINUX_VERSION_CODE
7265
7266static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
7267 struct net_device *dev, u8 *mac)
7268{
7269 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307270 hdd_context_t *pHddCtx;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007271 VOS_STATUS vos_status;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307272 int status;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007273 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07007274
Jeff Johnsone7245742012-09-05 17:12:55 -07007275 ENTER();
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307276 if ( NULL == pAdapter )
Jeff Johnson295189b2012-06-20 16:38:30 -07007277 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307278 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007279 return -EINVAL;
7280 }
7281
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307282 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7283 status = wlan_hdd_validate_context(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007284
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307285 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007286 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307287 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7288 "%s: HDD context is not valid", __func__);
7289 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007290 }
7291
Jeff Johnson295189b2012-06-20 16:38:30 -07007292 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07007293 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07007294 )
7295 {
7296 if( NULL == mac )
7297 {
7298 v_U16_t i;
7299 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
7300 {
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07007301 if ((pAdapter->aStaInfo[i].isUsed) &&
7302 (!pAdapter->aStaInfo[i].isDeauthInProgress))
Jeff Johnson295189b2012-06-20 16:38:30 -07007303 {
7304 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
7305 hddLog(VOS_TRACE_LEVEL_INFO,
7306 "%s: Delete STA with MAC::"
7307 "%02x:%02x:%02x:%02x:%02x:%02x",
7308 __func__,
7309 macAddr[0], macAddr[1], macAddr[2],
7310 macAddr[3], macAddr[4], macAddr[5]);
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07007311 vos_status = hdd_softap_sta_deauth(pAdapter, macAddr);
7312 if (VOS_IS_STATUS_SUCCESS(vos_status))
7313 pAdapter->aStaInfo[i].isDeauthInProgress = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007314 }
7315 }
7316 }
7317 else
7318 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007319
7320 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
7321 if (!VOS_IS_STATUS_SUCCESS(vos_status))
7322 {
7323 hddLog(VOS_TRACE_LEVEL_INFO,
7324 "%s: Skip this DEL STA as this is not used::"
7325 "%02x:%02x:%02x:%02x:%02x:%02x",
7326 __func__,
7327 mac[0], mac[1], mac[2],
7328 mac[3], mac[4], mac[5]);
7329 return -ENOENT;
7330 }
7331
7332 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
7333 {
7334 hddLog(VOS_TRACE_LEVEL_INFO,
7335 "%s: Skip this DEL STA as deauth is in progress::"
7336 "%02x:%02x:%02x:%02x:%02x:%02x",
7337 __func__,
7338 mac[0], mac[1], mac[2],
7339 mac[3], mac[4], mac[5]);
7340 return -ENOENT;
7341 }
7342
7343 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
7344
Jeff Johnson295189b2012-06-20 16:38:30 -07007345 hddLog(VOS_TRACE_LEVEL_INFO,
7346 "%s: Delete STA with MAC::"
7347 "%02x:%02x:%02x:%02x:%02x:%02x",
7348 __func__,
7349 mac[0], mac[1], mac[2],
7350 mac[3], mac[4], mac[5]);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007351
7352 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
7353 if (!VOS_IS_STATUS_SUCCESS(vos_status))
7354 {
7355 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
7356 hddLog(VOS_TRACE_LEVEL_INFO,
7357 "%s: STA removal failed for ::"
7358 "%02x:%02x:%02x:%02x:%02x:%02x",
7359 __func__,
7360 mac[0], mac[1], mac[2],
7361 mac[3], mac[4], mac[5]);
7362 return -ENOENT;
7363 }
7364
Jeff Johnson295189b2012-06-20 16:38:30 -07007365 }
7366 }
7367
7368 EXIT();
7369
7370 return 0;
7371}
7372
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007373static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
7374 struct net_device *dev, u8 *mac, struct station_parameters *params)
7375{
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007376 int status = -EPERM;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007377#ifdef FEATURE_WLAN_TDLS
7378 u32 mask, set;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007379 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007380 mask = params->sta_flags_mask;
7381
7382 set = params->sta_flags_set;
7383
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007384#ifdef WLAN_FEATURE_TDLS_DEBUG
7385 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7386 "%s: mask 0x%x set 0x%x " MAC_ADDRESS_STR,
7387 __func__, mask, set, MAC_ADDR_ARRAY(mac));
7388#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007389
7390 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
7391 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08007392 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007393 }
7394 }
7395#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007396 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07007397}
7398
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007399
7400#ifdef FEATURE_WLAN_LFR
Wilson Yang6507c4e2013-10-01 20:11:19 -07007401#define MAX_PMKSAIDS_IN_CACHE 8
7402
7403static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD local cache
7404static tANI_U32 PMKIDCacheIndex; // HDD local Cache index
7405
7406
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007407static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07007408 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007409{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307410 tANI_U32 j=0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007411 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7412 tHalHandle halHandle;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307413 eHalStatus result;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307414 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007415 tANI_U8 BSSIDMatched = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307416 hdd_context_t *pHddCtx;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307417
Jeff Johnsone7245742012-09-05 17:12:55 -07007418 ENTER();
7419
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307420 // Validate pAdapter
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307421 if ( NULL == pAdapter )
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007422 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307423 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007424 return -EINVAL;
7425 }
7426
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307427 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7428 status = wlan_hdd_validate_context(pHddCtx);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007429
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307430 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007431 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307432 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7433 "%s: HDD context is not valid", __func__);
7434 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007435 }
7436
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307437 // Retrieve halHandle
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007438 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
7439
Wilson Yang6507c4e2013-10-01 20:11:19 -07007440 for (j = 0; j < PMKIDCacheIndex; j++)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007441 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307442 if(vos_mem_compare(PMKIDCache[j].BSSID,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007443 pmksa->bssid, WNI_CFG_BSSID_LEN))
7444 {
7445 /* BSSID matched previous entry. Overwrite it. */
7446 BSSIDMatched = 1;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307447 vos_mem_copy(PMKIDCache[j].BSSID,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007448 pmksa->bssid, WNI_CFG_BSSID_LEN);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307449 vos_mem_copy(PMKIDCache[j].PMKID,
7450 pmksa->pmkid,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007451 CSR_RSN_PMKID_SIZE);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307452 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007453 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007454 dump_bssid(pmksa->bssid);
7455 dump_pmkid(halHandle, pmksa->pmkid);
7456 break;
7457 }
7458 }
7459
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07007460 /* Check we compared all entries,if then take the first slot now */
Wilson Yang6507c4e2013-10-01 20:11:19 -07007461 if(j == MAX_PMKSAIDS_IN_CACHE) PMKIDCacheIndex=0;
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07007462
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007463 if (!BSSIDMatched)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307464 {
7465 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
Wilson Yang6507c4e2013-10-01 20:11:19 -07007466 vos_mem_copy(PMKIDCache[PMKIDCacheIndex].BSSID,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307467 pmksa->bssid, ETHER_ADDR_LEN);
Wilson Yang6507c4e2013-10-01 20:11:19 -07007468 vos_mem_copy(PMKIDCache[PMKIDCacheIndex].PMKID,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307469 pmksa->pmkid,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007470 CSR_RSN_PMKID_SIZE);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307471 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Wilson Yang6507c4e2013-10-01 20:11:19 -07007472 __func__, PMKIDCacheIndex );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007473 dump_bssid(pmksa->bssid);
7474 dump_pmkid(halHandle, pmksa->pmkid);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307475 // Increment the HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007476 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
Wilson Yang6507c4e2013-10-01 20:11:19 -07007477 if (PMKIDCacheIndex <= (MAX_PMKSAIDS_IN_CACHE-1)) PMKIDCacheIndex++; else PMKIDCacheIndex = 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007478 }
7479
7480
7481 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307482 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007483 // __func__, i );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307484 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Wilson Yang6507c4e2013-10-01 20:11:19 -07007485 __func__, PMKIDCacheIndex );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007486 // Finally set the PMKSA ID Cache in CSR
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307487 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
7488 PMKIDCache,
Wilson Yang6507c4e2013-10-01 20:11:19 -07007489 PMKIDCacheIndex);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007490 return 0;
7491}
7492
7493
Wilson Yang6507c4e2013-10-01 20:11:19 -07007494
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007495static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Wilson Yang6507c4e2013-10-01 20:11:19 -07007496 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007497{
Wilson Yang6507c4e2013-10-01 20:11:19 -07007498 tANI_U32 j=0;
7499 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7500 tHalHandle halHandle;
7501 int status;
7502 tANI_U8 BSSIDMatched = 0;
7503 tANI_U8 *pBSSId;
7504 hdd_context_t *pHddCtx;
7505 int result = 0;
7506
7507 hddLog(VOS_TRACE_LEVEL_DEBUG, "%s: deleting PMKSA with PMKSA_ID %d .",
7508 __func__,pmksa->pmkid);
7509
7510 /* Validate pAdapter */
7511 if (NULL == pAdapter)
7512 {
7513 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__);
7514 return -EINVAL;
7515 }
7516
7517 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7518 status = wlan_hdd_validate_context(pHddCtx);
7519
7520 if (0 != status)
7521 {
7522 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7523 "%s: HDD context is not valid", __func__);
7524 return status;
7525 }
7526
7527 /*Retrieve halHandle*/
7528 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
7529
7530 /*in case index is 0,no entry to delete*/
7531 if (0 == PMKIDCacheIndex)
7532 {
7533 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid entry to delete" ,
7534 __func__);
7535 return -EINVAL;
7536 }
7537
7538 /*find the matching PMKSA entry from j=0 to (index-1),
7539 * and delete the matched one
7540 */
7541 for (j = 0; j<PMKIDCacheIndex; j++)
7542 {
7543 if (vos_mem_compare(PMKIDCache[j].BSSID,
7544 pmksa->bssid,
7545 WNI_CFG_BSSID_LEN))
7546 {
7547 /* BSSID matched entry */
7548 BSSIDMatched = 1;
7549
7550 if (j<PMKIDCacheIndex-1)
7551 {
7552 /*replace the matching entry with the last entry in HDD local cache*/
7553 vos_mem_copy(PMKIDCache[j].BSSID,
7554 PMKIDCache[PMKIDCacheIndex-1].BSSID,
7555 WNI_CFG_BSSID_LEN);
7556 vos_mem_copy(PMKIDCache[j].PMKID,
7557 PMKIDCache[PMKIDCacheIndex-1].PMKID,
7558 CSR_RSN_PMKID_SIZE);
7559 }
7560
7561 /*clear the last entry in HDD cache ---[index-1]*/
7562 pBSSId =(tANI_U8 *)(PMKIDCache[PMKIDCacheIndex-1].BSSID);
7563 vos_mem_zero(PMKIDCache[PMKIDCacheIndex-1].BSSID, WNI_CFG_BSSID_LEN);
7564 vos_mem_zero(PMKIDCache[PMKIDCacheIndex-1].PMKID, CSR_RSN_PMKID_SIZE);
7565
7566 /*reduce the PMKID array index*/
7567 PMKIDCacheIndex--;
7568
7569 /*delete the last PMKID cache in CSR*/
7570 result = sme_RoamDelPMKIDfromCache(halHandle, pAdapter->sessionId, pBSSId);
7571 if (0 != result)
7572 {
7573 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cannot delete PMKSA %d CONTENT.",
7574 __func__,PMKIDCacheIndex);
7575 }
7576
7577 dump_bssid(pmksa->bssid);
7578 dump_pmkid(halHandle,pmksa->pmkid);
7579
7580 break;
7581 }
7582 }
7583
7584 /* we compare all entries,but cannot find matching entry */
7585 if (j == MAX_PMKSAIDS_IN_CACHE && !BSSIDMatched)
7586 {
7587 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: No such PMKSA entry existed %d.",
7588 __func__,pmksa->bssid);
7589 dump_bssid(pmksa->bssid);
7590 dump_pmkid(halHandle, pmksa->pmkid);
7591 return -EINVAL;
7592 }
7593 return result;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007594}
7595
Wilson Yang6507c4e2013-10-01 20:11:19 -07007596
7597
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007598static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
7599{
Wilson Yang6507c4e2013-10-01 20:11:19 -07007600 tANI_U32 j=0;
7601 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7602 tHalHandle halHandle;
7603 hdd_context_t *pHddCtx;
7604 tANI_U8 *pBSSId;
7605 int status;
7606 int result;
7607
7608 hddLog(VOS_TRACE_LEVEL_DEBUG, "%s: flushing PMKSA ",__func__);
7609
7610 /* Validate pAdapter */
7611 if (NULL == pAdapter)
7612 {
7613 hddLog(VOS_TRACE_LEVEL_ERROR,
7614 "%s: Invalid Adapter" ,__func__);
7615 return -EINVAL;
7616 }
7617
7618 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7619 status = wlan_hdd_validate_context(pHddCtx);
7620
7621 if (0 != status)
7622 {
7623 hddLog(VOS_TRACE_LEVEL_ERROR,
7624 "%s: HDD context is not valid", __func__);
7625 return status;
7626 }
7627
7628 /*Retrieve halHandle*/
7629 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
7630
7631 /*in case index is 0,no entry to delete*/
7632 if (0 == PMKIDCacheIndex)
7633 {
7634 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid entry to delete" ,
7635 __func__);
7636 return -EINVAL;
7637 }
7638
7639 /*delete all the PMKSA one by one */
7640 for (j = 0; j<PMKIDCacheIndex; j++)
7641 {
7642 /*clear the entry in HDD cache 0--index-1 */
7643 pBSSId =(tANI_U8 *)(PMKIDCache[j].BSSID);
7644 vos_mem_zero(PMKIDCache[j].BSSID, WNI_CFG_BSSID_LEN);
7645 vos_mem_zero(PMKIDCache[j].PMKID, CSR_RSN_PMKID_SIZE);
7646
7647 /*delete the PMKID in CSR*/
7648 result = sme_RoamDelPMKIDfromCache(halHandle, pAdapter->sessionId, pBSSId);
7649
7650 if (0!= result)
7651 {
7652 hddLog(VOS_TRACE_LEVEL_ERROR ,"%s cannot flush PMKIDCache %d.",
7653 __func__,j);
7654 }
7655 }
7656
7657 PMKIDCacheIndex = 0;
7658 return result;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007659}
7660#endif
7661
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007662#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307663static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007664 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
7665{
7666 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7667 hdd_station_ctx_t *pHddStaCtx;
7668
7669 if (NULL == pAdapter)
7670 {
7671 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
7672 return -ENODEV;
7673 }
7674
7675 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7676
7677 // Added for debug on reception of Re-assoc Req.
7678 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
7679 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307680 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007681 ftie->ie_len);
7682 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
7683 }
7684
7685#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307686 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007687 ftie->ie_len);
7688#endif
7689
7690 // Pass the received FT IEs to SME
Gopichand Nakkala356fb102013-03-06 12:34:04 +05307691 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
7692 (const u8 *)ftie->ie,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007693 ftie->ie_len);
7694 return 0;
7695}
7696#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007697
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307698#ifdef FEATURE_WLAN_SCAN_PNO
7699
7700void hdd_cfg80211_sched_scan_done_callback(void *callbackContext,
7701 tSirPrefNetworkFoundInd *pPrefNetworkFoundInd)
7702{
7703 int ret;
7704 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
7705 hdd_context_t *pHddCtx;
7706
7707 if (NULL == pAdapter)
7708 {
7709 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7710 "%s: HDD adapter is Null", __func__);
7711 return ;
7712 }
7713
7714 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7715 if (NULL == pHddCtx)
7716 {
7717 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7718 "%s: HDD context is Null!!!", __func__);
7719 return ;
7720 }
7721
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307722 spin_lock(&pHddCtx->schedScan_lock);
7723 if (TRUE == pHddCtx->isWiphySuspended)
7724 {
7725 pHddCtx->isSchedScanUpdatePending = TRUE;
7726 spin_unlock(&pHddCtx->schedScan_lock);
7727 hddLog(VOS_TRACE_LEVEL_INFO,
7728 "%s: Update cfg80211 scan database after it resume", __func__);
7729 return ;
7730 }
7731 spin_unlock(&pHddCtx->schedScan_lock);
7732
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307733 ret = wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter);
7734
7735 if (0 > ret)
7736 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
7737
7738 cfg80211_sched_scan_results(pHddCtx->wiphy);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307739 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7740 "%s: cfg80211 scan result database updated", __func__);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307741}
7742
7743/*
7744 * FUNCTION: wlan_hdd_cfg80211_sched_scan_start
7745 * NL interface to enable PNO
7746 */
7747static int wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy,
7748 struct net_device *dev, struct cfg80211_sched_scan_request *request)
7749{
7750 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7751 tpSirPNOScanReq pPnoRequest = NULL;
7752 hdd_context_t *pHddCtx;
7753 tHalHandle hHal;
Madan Mohan Koyyalamudi1d16f462013-08-27 16:25:34 +05307754 v_U32_t i, indx, num_ch, tempInterval;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307755 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
7756 u8 channels_allowed[WNI_CFG_VALID_CHANNEL_LIST_LEN];
7757 v_U32_t num_channels_allowed = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7758 eHalStatus status = eHAL_STATUS_FAILURE;
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307759 int ret = 0;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307760
7761 if (NULL == pAdapter)
7762 {
7763 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7764 "%s: HDD adapter is Null", __func__);
7765 return -ENODEV;
7766 }
7767
7768 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307769 ret = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307770
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307771 if (0 != ret)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307772 {
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05307773 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7774 "%s: HDD context is not valid", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307775 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307776 }
7777
7778 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
7779 if (NULL == hHal)
7780 {
7781 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7782 "%s: HAL context is Null!!!", __func__);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307783 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307784 }
7785
7786 pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq));
7787 if (NULL == pPnoRequest)
7788 {
7789 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7790 "%s: vos_mem_malloc failed", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307791 return -ENOMEM;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307792 }
7793
Madan Mohan Koyyalamudic3f04352013-09-26 19:21:48 +05307794 memset(pPnoRequest, 0, sizeof (tSirPNOScanReq));
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307795 pPnoRequest->enable = 1; /*Enable PNO */
7796 pPnoRequest->ucNetworksCount = request->n_match_sets;
7797
7798 if (( !pPnoRequest->ucNetworksCount ) ||
7799 ( pPnoRequest->ucNetworksCount > SIR_PNO_MAX_SUPP_NETWORKS ))
7800 {
7801 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7802 "Network input is not correct");
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307803 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307804 goto error;
7805 }
7806
7807 if ( SIR_PNO_MAX_NETW_CHANNELS_EX < request->n_channels )
7808 {
7809 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7810 "Incorrect number of channels");
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307811 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307812 goto error;
7813 }
7814
7815 /* Framework provides one set of channels(all)
7816 * common for all saved profile */
7817 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
7818 channels_allowed, &num_channels_allowed))
7819 {
7820 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7821 "%s: failed to get valid channel list", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307822 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307823 goto error;
7824 }
7825 /* Checking each channel against allowed channel list */
7826 num_ch = 0;
7827 for (i = 0; i < request->n_channels; i++)
7828 {
7829 for (indx = 0; indx < num_channels_allowed; indx++)
7830 {
7831 if (request->channels[i]->hw_value == channels_allowed[indx])
7832 {
7833 valid_ch[num_ch++] = request->channels[i]->hw_value;
7834 break ;
7835 }
7836 }
7837 }
7838
7839 /* Filling per profile params */
7840 for (i = 0; i < pPnoRequest->ucNetworksCount; i++)
7841 {
7842 pPnoRequest->aNetworks[i].ssId.length =
7843 request->match_sets[i].ssid.ssid_len;
7844
7845 if (( 0 == pPnoRequest->aNetworks[i].ssId.length ) ||
7846 ( pPnoRequest->aNetworks[i].ssId.length > 32 ) )
7847 {
7848 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7849 "SSID Len %d is not correct for network %d",
7850 pPnoRequest->aNetworks[i].ssId.length, i);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307851 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307852 goto error;
7853 }
7854
7855 memcpy(pPnoRequest->aNetworks[i].ssId.ssId,
7856 request->match_sets[i].ssid.ssid,
7857 request->match_sets[i].ssid.ssid_len);
7858 pPnoRequest->aNetworks[i].authentication = 0; /*eAUTH_TYPE_ANY*/
7859 pPnoRequest->aNetworks[i].encryption = 0; /*eED_ANY*/
7860 pPnoRequest->aNetworks[i].bcastNetwType = 0; /*eBCAST_UNKNOWN*/
7861
7862 /*Copying list of valid channel into request */
7863 memcpy(pPnoRequest->aNetworks[i].aChannels, valid_ch, num_ch);
7864 pPnoRequest->aNetworks[i].ucChannelCount = num_ch;
7865
7866 pPnoRequest->aNetworks[i].rssiThreshold = 0; //Default value
7867 }
7868
Madan Mohan Koyyalamudia7765d52013-09-18 16:49:56 +05307869 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7870 "request->ie_len = %d", request->ie_len);
7871 if ((0 < request->ie_len) && (NULL != request->ie))
7872 {
7873 pPnoRequest->us24GProbeTemplateLen = request->ie_len;
7874 memcpy(&pPnoRequest->p24GProbeTemplate, request->ie,
7875 pPnoRequest->us24GProbeTemplateLen);
7876
7877 pPnoRequest->us5GProbeTemplateLen = request->ie_len;
7878 memcpy(&pPnoRequest->p5GProbeTemplate, request->ie,
7879 pPnoRequest->us5GProbeTemplateLen);
7880 }
7881
Madan Mohan Koyyalamudi1d16f462013-08-27 16:25:34 +05307882 /* Driver gets only one time interval which is hardcoded in
7883 * supplicant for 10000ms. Taking power consumption into account 6 timers
7884 * will be used, Timervalue is increased exponentially i.e 10,20,40,
7885 * 80,160,320 secs. And number of scan cycle for each timer
7886 * is configurable through INI param gPNOScanTimerRepeatValue.
7887 * If it is set to 0 only one timer will be used and PNO scan cycle
7888 * will be repeated after each interval specified by supplicant
7889 * till PNO is disabled.
7890 */
7891 if (0 == pHddCtx->cfg_ini->configPNOScanTimerRepeatValue)
7892 pPnoRequest->scanTimers.ucScanTimersCount = HDD_PNO_SCAN_TIMERS_SET_ONE;
7893 else
7894 pPnoRequest->scanTimers.ucScanTimersCount =
7895 HDD_PNO_SCAN_TIMERS_SET_MULTIPLE;
7896
7897 tempInterval = (request->interval)/1000;
7898 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7899 "Base scan interval = %d PNOScanTimerRepeatValue = %d",
7900 tempInterval, pHddCtx->cfg_ini->configPNOScanTimerRepeatValue);
7901 for ( i = 0; i < pPnoRequest->scanTimers.ucScanTimersCount; i++)
7902 {
7903 pPnoRequest->scanTimers.aTimerValues[i].uTimerRepeat =
7904 pHddCtx->cfg_ini->configPNOScanTimerRepeatValue;
7905 pPnoRequest->scanTimers.aTimerValues[i].uTimerValue = tempInterval;
7906 tempInterval *= 2;
7907 }
7908 //Repeat last timer until pno disabled.
7909 pPnoRequest->scanTimers.aTimerValues[i-1].uTimerRepeat = 0;
7910
Madan Mohan Koyyalamudid206c7b2013-09-26 22:54:51 +05307911 pPnoRequest->modePNO = SIR_PNO_MODE_IMMEDIATE;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307912
7913 status = sme_SetPreferredNetworkList(WLAN_HDD_GET_HAL_CTX(pAdapter),
7914 pPnoRequest, pAdapter->sessionId,
7915 hdd_cfg80211_sched_scan_done_callback, pAdapter);
7916 if (eHAL_STATUS_SUCCESS != status)
7917 {
7918 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7919 "Failed to enable PNO");
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307920 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307921 goto error;
7922 }
7923
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307924 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7925 "PNO scanRequest offloaded");
7926
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307927error:
7928 vos_mem_free(pPnoRequest);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307929 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307930}
7931
7932/*
7933 * FUNCTION: wlan_hdd_cfg80211_sched_scan_stop
7934 * NL interface to disable PNO
7935 */
7936static int wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy,
7937 struct net_device *dev)
7938{
7939 eHalStatus status = eHAL_STATUS_FAILURE;
7940 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7941 hdd_context_t *pHddCtx;
7942 tHalHandle hHal;
7943 tpSirPNOScanReq pPnoRequest = NULL;
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307944 int ret = 0;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307945
7946 ENTER();
7947
7948 if (NULL == pAdapter)
7949 {
7950 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7951 "%s: HDD adapter is Null", __func__);
7952 return -ENODEV;
7953 }
7954
7955 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307956
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307957 if (NULL == pHddCtx)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307958 {
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05307959 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307960 "%s: HDD context is Null", __func__);
7961 return -ENODEV;
7962 }
7963
7964 /* The return 0 is intentional when isLogpInProgress and
7965 * isLoadUnloadInProgress. We did observe a crash due to a return of
7966 * failure in sched_scan_stop , especially for a case where the unload
7967 * of the happens at the same time. The function __cfg80211_stop_sched_scan
7968 * was clearing rdev->sched_scan_req only when the sched_scan_stop returns
7969 * success. If it returns a failure , then its next invocation due to the
7970 * clean up of the second interface will have the dev pointer corresponding
7971 * to the first one leading to a crash.
7972 */
7973 if (pHddCtx->isLogpInProgress)
7974 {
7975 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7976 "%s: LOGP in Progress. Ignore!!!", __func__);
7977 return ret;
7978 }
7979
7980 if (pHddCtx->isLoadUnloadInProgress)
7981 {
7982 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7983 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
7984 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307985 }
7986
7987 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
7988 if (NULL == hHal)
7989 {
7990 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7991 "%s: HAL context is Null!!!", __func__);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307992 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307993 }
7994
7995 pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq));
7996 if (NULL == pPnoRequest)
7997 {
7998 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7999 "%s: vos_mem_malloc failed", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308000 return -ENOMEM;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308001 }
8002
8003 memset(pPnoRequest, 0, sizeof (tSirPNOScanReq));
8004 pPnoRequest->enable = 0; /* Disable PNO */
8005 pPnoRequest->ucNetworksCount = 0;
8006
8007 status = sme_SetPreferredNetworkList(hHal, pPnoRequest,
8008 pAdapter->sessionId,
8009 NULL, pAdapter);
8010 if (eHAL_STATUS_SUCCESS != status)
8011 {
8012 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8013 "Failed to disabled PNO");
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308014 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308015 }
8016
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308017 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8018 "%s: PNO scan disabled", __func__);
8019
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308020 vos_mem_free(pPnoRequest);
8021
8022 EXIT();
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308023 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308024}
8025
8026#endif /*FEATURE_WLAN_SCAN_PNO*/
8027
8028
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008029#ifdef FEATURE_WLAN_TDLS
8030static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
8031 u8 *peer, u8 action_code, u8 dialog_token,
8032 u16 status_code, const u8 *buf, size_t len)
8033{
8034
8035 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8036 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008037 u8 peerMac[6];
8038 VOS_STATUS status;
Gopichand Nakkala05922802013-03-14 12:23:19 -07008039 int max_sta_failed = 0;
Hoonki Leea34dd892013-02-05 22:56:02 -08008040 int responder;
Hoonki Leed37cbb32013-04-20 00:31:14 -07008041 long rc;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008042
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008043 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008044 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308045 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008046 "Invalid arguments");
8047 return -EINVAL;
8048 }
8049
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08008050 if (pHddCtx->isLogpInProgress)
8051 {
8052 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8053 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07008054 wlan_hdd_tdls_set_link_status(pAdapter, peer, eTDLS_LINK_IDLE);
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08008055 return -EBUSY;
8056 }
8057
Hoonki Lee27511902013-03-14 18:19:06 -07008058 if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008059 {
Hoonki Lee27511902013-03-14 18:19:06 -07008060 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
8061 "%s: TDLS mode is disabled OR not enabled in FW."
8062 MAC_ADDRESS_STR " action %d declined.",
8063 __func__, MAC_ADDR_ARRAY(peer), action_code);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008064 return -ENOTSUPP;
8065 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08008066
Hoonki Lee27511902013-03-14 18:19:06 -07008067 /* other than teardown frame, other mgmt frames are not sent if disabled */
8068 if (SIR_MAC_TDLS_TEARDOWN != action_code)
8069 {
8070 /* if tdls_mode is disabled to respond to peer's request */
8071 if (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode)
8072 {
8073 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
8074 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07008075 " TDLS mode is disabled. action %d declined.",
8076 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee27511902013-03-14 18:19:06 -07008077
8078 return -ENOTSUPP;
8079 }
8080 }
8081
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008082 if (WLAN_IS_TDLS_SETUP_ACTION(action_code))
8083 {
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308084 if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, peer, TRUE))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008085 {
8086 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008087 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07008088 " TDLS setup is ongoing. action %d declined.",
8089 __func__, MAC_ADDR_ARRAY(peer), action_code);
8090 return -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008091 }
8092 }
8093
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008094 if (SIR_MAC_TDLS_SETUP_REQ == action_code ||
8095 SIR_MAC_TDLS_SETUP_RSP == action_code )
Lee Hoonkic1262f22013-01-24 21:59:00 -08008096 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08008097 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
Lee Hoonkic1262f22013-01-24 21:59:00 -08008098 {
8099 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
8100 we return error code at 'add_station()'. Hence we have this
8101 check again in addtion to add_station().
8102 Anyway, there is no hard to double-check. */
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008103 if (SIR_MAC_TDLS_SETUP_REQ == action_code)
Lee Hoonkic1262f22013-01-24 21:59:00 -08008104 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008105 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8106 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07008107 " TDLS Max peer already connected. action %d declined.",
8108 __func__, MAC_ADDR_ARRAY(peer), action_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07008109 goto error;
Lee Hoonkic1262f22013-01-24 21:59:00 -08008110 }
8111 else
8112 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008113 /* maximum reached. tweak to send error code to peer and return
8114 error code to supplicant */
Lee Hoonkic1262f22013-01-24 21:59:00 -08008115 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008116 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8117 "%s: " MAC_ADDRESS_STR
8118 " TDLS Max peer already connected send response status %d",
8119 __func__, MAC_ADDR_ARRAY(peer), status_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07008120 max_sta_failed = -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008121 /* fall through to send setup resp with failure status
8122 code */
Lee Hoonkic1262f22013-01-24 21:59:00 -08008123 }
8124 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008125 else
8126 {
8127 hddTdlsPeer_t *pTdlsPeer;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308128 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07008129 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008130 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008131 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07008132 "%s:" MAC_ADDRESS_STR " already connected. action %d declined.",
8133 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008134 return -EPERM;
8135 }
8136 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08008137 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008138 vos_mem_copy(peerMac, peer, 6);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008139
Hoonki Lee1090c6a2013-01-16 17:40:54 -08008140#ifdef WLAN_FEATURE_TDLS_DEBUG
8141 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008142 "%s: " MAC_ADDRESS_STR " action %d, dialog_token %d status %d, len = %d",
8143 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
8144 action_code, dialog_token, status_code, len);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08008145#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008146
Hoonki Leea34dd892013-02-05 22:56:02 -08008147 /*Except teardown responder will not be used so just make 0*/
8148 responder = 0;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008149 if (SIR_MAC_TDLS_TEARDOWN == action_code)
Hoonki Leea34dd892013-02-05 22:56:02 -08008150 {
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -07008151
8152 hddTdlsPeer_t *pTdlsPeer;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308153 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peerMac, TRUE);
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -07008154
8155 if(pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
8156 responder = pTdlsPeer->is_responder;
8157 else
Hoonki Leea34dd892013-02-05 22:56:02 -08008158 {
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -07008159 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8160 "%s: " MAC_ADDRESS_STR " peer doesn't exist or not connected %d dialog_token %d status %d, len = %d",
8161 __func__, MAC_ADDR_ARRAY(peer), (NULL == pTdlsPeer) ? -1 : pTdlsPeer->link_status,
8162 dialog_token, status_code, len);
8163 return -EPERM;
Hoonki Leea34dd892013-02-05 22:56:02 -08008164 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008165 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008166
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05308167 /* For explicit trigger of DIS_REQ come out of BMPS for
8168 successfully receiving DIS_RSP from peer. */
Hoonki Lee14621352013-04-16 17:51:19 -07008169 if ((SIR_MAC_TDLS_SETUP_RSP == action_code) ||
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05308170 (SIR_MAC_TDLS_DIS_RSP == action_code) ||
8171 (SIR_MAC_TDLS_DIS_REQ == action_code))
Hoonki Lee14621352013-04-16 17:51:19 -07008172 {
8173 if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter)))
8174 {
8175 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05308176 "%s: Sending frame action_code %u.Disable BMPS", __func__, action_code);
Hoonki Lee14621352013-04-16 17:51:19 -07008177 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
8178 }
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05308179 if (SIR_MAC_TDLS_DIS_REQ != action_code)
8180 wlan_hdd_tdls_set_cap(pAdapter, peerMac, eTDLS_CAP_SUPPORTED);
Hoonki Lee14621352013-04-16 17:51:19 -07008181 }
8182
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008183 /* make sure doesn't call send_mgmt() while it is pending */
8184 if (TDLS_CTX_MAGIC == pAdapter->mgmtTxCompletionStatus)
8185 {
8186 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8187 "%s: " MAC_ADDRESS_STR " action %d couldn't sent, as one is pending. return EBUSY\n",
8188 __func__, MAC_ADDR_ARRAY(peer), action_code);
8189 return -EBUSY;
8190 }
8191
8192 pAdapter->mgmtTxCompletionStatus = TDLS_CTX_MAGIC;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008193 INIT_COMPLETION(pAdapter->tdls_mgmt_comp);
8194
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008195 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
Hoonki Leea34dd892013-02-05 22:56:02 -08008196 peerMac, action_code, dialog_token, status_code, (tANI_U8 *)buf, len, responder);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008197
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008198 if (VOS_STATUS_SUCCESS != status)
8199 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008200 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8201 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008202 pAdapter->mgmtTxCompletionStatus = FALSE;
Hoonki Lee14621352013-04-16 17:51:19 -07008203 wlan_hdd_tdls_check_bmps(pAdapter);
8204 goto error;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008205 }
8206
Hoonki Leed37cbb32013-04-20 00:31:14 -07008207 rc = wait_for_completion_interruptible_timeout(&pAdapter->tdls_mgmt_comp,
8208 msecs_to_jiffies(WAIT_TIME_TDLS_MGMT));
8209
8210 if ((rc <= 0) || (TRUE != pAdapter->mgmtTxCompletionStatus))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008211 {
Hoonki Leed37cbb32013-04-20 00:31:14 -07008212 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8213 "%s: Mgmt Tx Completion failed status %ld TxCompletion %lu",
8214 __func__, rc, pAdapter->mgmtTxCompletionStatus);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008215 pAdapter->mgmtTxCompletionStatus = FALSE;
Hoonki Leed37cbb32013-04-20 00:31:14 -07008216 wlan_hdd_tdls_check_bmps(pAdapter);
8217 goto error;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008218 }
8219
Gopichand Nakkala05922802013-03-14 12:23:19 -07008220 if (max_sta_failed)
Hoonki Lee14621352013-04-16 17:51:19 -07008221 {
8222 wlan_hdd_tdls_check_bmps(pAdapter);
Gopichand Nakkala05922802013-03-14 12:23:19 -07008223 return max_sta_failed;
Hoonki Lee14621352013-04-16 17:51:19 -07008224 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008225
Hoonki Leea34dd892013-02-05 22:56:02 -08008226 if (SIR_MAC_TDLS_SETUP_RSP == action_code)
8227 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08008228 wlan_hdd_tdls_set_responder(pAdapter, peerMac, TRUE);
Hoonki Leea34dd892013-02-05 22:56:02 -08008229 }
8230 else if (SIR_MAC_TDLS_SETUP_CNF == action_code)
8231 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08008232 wlan_hdd_tdls_set_responder(pAdapter, peerMac, FALSE);
Hoonki Leea34dd892013-02-05 22:56:02 -08008233 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008234
8235 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07008236error:
8237 /* max_sta_failed ; we didn't set to CONNECTING for this case,
8238 because we already know that this transaction will be failed,
8239 but we weren't sure if supplicant call DISABLE_LINK or not. So,
8240 to be safe, do not change the state mahine.
8241 */
8242 if(max_sta_failed == 0 &&
8243 (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
8244 wlan_hdd_tdls_set_link_status(pAdapter, peerMac, eTDLS_LINK_IDLE);
8245 return -EPERM;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008246}
8247
8248static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
8249 u8 *peer, enum nl80211_tdls_operation oper)
8250{
8251 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8252 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308253 int status;
Hoonki Lee1090c6a2013-01-16 17:40:54 -08008254#ifdef WLAN_FEATURE_TDLS_DEBUG
8255 const char *tdls_oper_str[]= {
8256 "NL80211_TDLS_DISCOVERY_REQ",
8257 "NL80211_TDLS_SETUP",
8258 "NL80211_TDLS_TEARDOWN",
8259 "NL80211_TDLS_ENABLE_LINK",
8260 "NL80211_TDLS_DISABLE_LINK",
Gopichand Nakkala29d00192013-06-20 19:03:52 +05308261 "NL80211_TDLS_UNKNOWN_OPER"};
Hoonki Lee1090c6a2013-01-16 17:40:54 -08008262#endif
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008263 hddTdlsPeer_t *pTdlsPeer;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008264
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308265 if ( NULL == peer )
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008266 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008267 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Chilam Ngc4244af2013-04-01 15:37:32 -07008268 "%s: Invalid arguments", __func__);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008269 return -EINVAL;
8270 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08008271
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308272 status = wlan_hdd_validate_context(pHddCtx);
8273
8274 if (0 != status)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08008275 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308276 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8277 "%s: HDD context is not valid", __func__);
8278 return status;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08008279 }
8280
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308281 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008282
8283 if ( NULL == pTdlsPeer ) {
8284 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: " MAC_ADDRESS_STR " (oper %d) not exsting. ignored",
8285 __func__, MAC_ADDR_ARRAY(peer), (int)oper);
8286 return -EINVAL;
8287 }
8288
Hoonki Lee1090c6a2013-01-16 17:40:54 -08008289#ifdef WLAN_FEATURE_TDLS_DEBUG
8290 if((int)oper > 4)
8291 oper = 5;
8292
8293 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008294 "%s: " MAC_ADDRESS_STR " link_status %d (%s) ", "tdls_oper",
8295 MAC_ADDR_ARRAY(peer), pTdlsPeer->link_status,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008296 tdls_oper_str[(int)oper]);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08008297#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008298
8299 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -08008300 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008301 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08008302 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Chilam Ngc4244af2013-04-01 15:37:32 -07008303 "TDLS Disabled in INI OR not enabled in FW. "
8304 "Cannot process TDLS commands");
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008305 return -ENOTSUPP;
8306 }
8307
8308 switch (oper) {
8309 case NL80211_TDLS_ENABLE_LINK:
8310 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008311 VOS_STATUS status;
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308312 tCsrTdlsLinkEstablishParams tdlsLinkEstablishParams;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008313
Gopichand Nakkala2f4a2822013-04-17 11:22:01 -07008314 if (!TDLS_STA_INDEX_VALID(pTdlsPeer->staId))
8315 {
8316 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Staion Index %u "
8317 MAC_ADDRESS_STR " failed",
8318 __func__, pTdlsPeer->staId, MAC_ADDR_ARRAY(peer));
8319 return -EINVAL;
8320 }
8321
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008322 if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status)
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008323 {
Gopichand Nakkala24be5312013-07-02 16:47:12 +05308324 long ret;
Madan Mohan Koyyalamudice419872013-09-13 19:36:52 +05308325 if (IS_ADVANCE_TDLS_ENABLE) {
Gopichand Nakkala24be5312013-07-02 16:47:12 +05308326
Madan Mohan Koyyalamudice419872013-09-13 19:36:52 +05308327 if (0 != wlan_hdd_tdls_get_link_establish_params(
8328 pAdapter, peer,&tdlsLinkEstablishParams)) {
8329 return -EINVAL;
8330 }
8331 INIT_COMPLETION(pAdapter->tdls_link_establish_req_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308332
Madan Mohan Koyyalamudice419872013-09-13 19:36:52 +05308333 sme_SendTdlsLinkEstablishParams(WLAN_HDD_GET_HAL_CTX(pAdapter),
8334 pAdapter->sessionId, peer, &tdlsLinkEstablishParams);
8335 /* Send TDLS peer UAPSD capabilities to the firmware and
8336 * register with the TL on after the response for this operation
8337 * is received .
8338 */
8339 ret = wait_for_completion_interruptible_timeout(
8340 &pAdapter->tdls_link_establish_req_comp,
8341 msecs_to_jiffies(WAIT_TIME_TDLS_LINK_ESTABLISH_REQ));
8342 if (ret <= 0)
8343 {
8344 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8345 "%s: Link Establish Request Faled Status %ld",
8346 __func__, ret);
8347 return -EINVAL;
8348 }
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308349 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07008350 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
Gopichand Nakkala471708b2013-06-04 20:03:01 +05308351 /* Mark TDLS client Authenticated .*/
8352 status = WLANTL_ChangeSTAState( pHddCtx->pvosContext,
8353 pTdlsPeer->staId,
8354 WLANTL_STA_AUTHENTICATED);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07008355 if (VOS_STATUS_SUCCESS == status)
8356 {
Hoonki Lee14621352013-04-16 17:51:19 -07008357 if (pTdlsPeer->is_responder == 0)
8358 {
8359 v_U8_t staId = (v_U8_t)pTdlsPeer->staId;
8360
8361 wlan_hdd_tdls_timer_restart(pAdapter,
8362 &pTdlsPeer->initiatorWaitTimeoutTimer,
8363 WAIT_TIME_TDLS_INITIATOR);
8364 /* suspend initiator TX until it receives direct packet from the
8365 reponder or WAIT_TIME_TDLS_INITIATOR timer expires */
8366 WLANTL_SuspendDataTx( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
8367 &staId, NULL);
8368 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07008369 wlan_hdd_tdls_increment_peer_count(pAdapter);
8370 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008371 wlan_hdd_tdls_check_bmps(pAdapter);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308372
8373 /* Update TL about the UAPSD masks , to route the packets to firmware */
Gopichand Nakkala574f6d12013-06-27 19:38:43 +05308374 if ((TRUE == pHddCtx->cfg_ini->fEnableTDLSBufferSta)
8375 || pHddCtx->cfg_ini->fTDLSUapsdMask )
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308376 {
Gopichand Nakkala574f6d12013-06-27 19:38:43 +05308377 int ac;
8378 uint8 ucAc[4] = { WLANTL_AC_VO,
8379 WLANTL_AC_VI,
8380 WLANTL_AC_BK,
8381 WLANTL_AC_BE };
8382 uint8 tlTid[4] = { 7, 5, 2, 3 } ;
8383 for(ac=0; ac < 4; ac++)
8384 {
8385 status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
8386 pTdlsPeer->staId, ucAc[ac],
8387 tlTid[ac], tlTid[ac], 0, 0,
8388 WLANTL_BI_DIR );
8389 }
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308390 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008391 }
8392
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008393 }
8394 break;
8395 case NL80211_TDLS_DISABLE_LINK:
Lee Hoonkic1262f22013-01-24 21:59:00 -08008396 {
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008397 if(TDLS_STA_INDEX_VALID(pTdlsPeer->staId))
Lee Hoonkic1262f22013-01-24 21:59:00 -08008398 {
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07008399 long status;
8400
8401 INIT_COMPLETION(pAdapter->tdls_del_station_comp);
8402
Lee Hoonkic1262f22013-01-24 21:59:00 -08008403 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
8404 pAdapter->sessionId, peer );
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07008405
8406 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_del_station_comp,
8407 msecs_to_jiffies(WAIT_TIME_TDLS_DEL_STA));
8408 if (status <= 0)
8409 {
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008410 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_IDLE);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07008411 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8412 "%s: Del station failed status %ld",
8413 __func__, status);
8414 return -EPERM;
8415 }
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008416 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_IDLE);
Lee Hoonkic1262f22013-01-24 21:59:00 -08008417 }
8418 else
8419 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008420 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8421 "%s: TDLS Peer Station doesn't exist.", __func__);
Lee Hoonkic1262f22013-01-24 21:59:00 -08008422 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08008423 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008424 break;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008425 case NL80211_TDLS_TEARDOWN:
8426 case NL80211_TDLS_SETUP:
8427 case NL80211_TDLS_DISCOVERY_REQ:
8428 /* We don't support in-driver setup/teardown/discovery */
8429 return -ENOTSUPP;
8430 default:
8431 return -ENOTSUPP;
8432 }
8433 return 0;
8434}
Chilam NG571c65a2013-01-19 12:27:36 +05308435
8436int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
8437 struct net_device *dev, u8 *peer)
8438{
8439 hddLog(VOS_TRACE_LEVEL_INFO, "tdls send discover req: %x %x %x %x %x %x",
8440 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5]);
8441
8442 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
8443 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
8444}
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008445#endif
8446
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308447#ifdef WLAN_FEATURE_GTK_OFFLOAD
8448/*
8449 * FUNCTION: wlan_hdd_cfg80211_update_replayCounterCallback
8450 * Callback rountine called upon receiving response for
8451 * get offload info
8452 */
8453void wlan_hdd_cfg80211_update_replayCounterCallback(void *callbackContext,
8454 tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoRsp)
8455{
8456
8457 hdd_adapter_t *pAdapter = (hdd_adapter_t *)callbackContext;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308458 tANI_U8 tempReplayCounter[8];
8459 hdd_station_ctx_t *pHddStaCtx;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308460
8461 ENTER();
8462
8463 if (NULL == pAdapter)
8464 {
8465 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8466 "%s: HDD adapter is Null", __func__);
8467 return ;
8468 }
8469
8470 if (NULL == pGtkOffloadGetInfoRsp)
8471 {
8472 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8473 "%s: pGtkOffloadGetInfoRsp is Null", __func__);
8474 return ;
8475 }
8476
8477 if (VOS_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus)
8478 {
8479 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8480 "%s: wlan Failed to get replay counter value",
8481 __func__);
8482 return ;
8483 }
8484
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308485 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8486 /* Update replay counter */
8487 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
8488 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
8489
8490 {
8491 /* changing from little to big endian since supplicant
8492 * works on big endian format
8493 */
8494 int i;
8495 tANI_U8 *p = (tANI_U8 *)&pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
8496
8497 for (i = 0; i < 8; i++)
8498 {
8499 tempReplayCounter[7-i] = (tANI_U8)p[i];
8500 }
8501 }
8502
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308503 /* Update replay counter to NL */
8504 cfg80211_gtk_rekey_notify(pAdapter->dev, pGtkOffloadGetInfoRsp->bssId,
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308505 tempReplayCounter, GFP_KERNEL);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308506}
8507
8508/*
8509 * FUNCTION: wlan_hdd_cfg80211_set_rekey_data
8510 * This function is used to offload GTK rekeying job to the firmware.
8511 */
8512int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
8513 struct cfg80211_gtk_rekey_data *data)
8514{
8515 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8516 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8517 hdd_station_ctx_t *pHddStaCtx;
8518 tHalHandle hHal;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308519 int result;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308520 tSirGtkOffloadParams hddGtkOffloadReqParams;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308521 eHalStatus status = eHAL_STATUS_FAILURE;
8522
8523 ENTER();
8524
8525 if (NULL == pAdapter)
8526 {
8527 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8528 "%s: HDD adapter is Null", __func__);
8529 return -ENODEV;
8530 }
8531
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308532 result = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308533
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308534 if (0 != result)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308535 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308536 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8537 "%s: HDD context is not valid", __func__);
8538 return result;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308539 }
8540
8541 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8542 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8543 if (NULL == hHal)
8544 {
8545 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8546 "%s: HAL context is Null!!!", __func__);
8547 return -EAGAIN;
8548 }
8549
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308550 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
8551 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck, NL80211_KCK_LEN);
8552 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek, NL80211_KEK_LEN);
8553 memcpy(pHddStaCtx->gtkOffloadReqParams.bssId, &pHddStaCtx->conn_info.bssId,
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308554 WNI_CFG_BSSID_LEN);
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308555 {
8556 /* changing from big to little endian since driver
8557 * works on little endian format
8558 */
8559 tANI_U8 *p =
8560 (tANI_U8 *)&pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter;
8561 int i;
8562
8563 for (i = 0; i < 8; i++)
8564 {
8565 p[7-i] = data->replay_ctr[i];
8566 }
8567 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308568
8569 if (TRUE == pHddCtx->hdd_wlan_suspended)
8570 {
8571 /* if wlan is suspended, enable GTK offload directly from here */
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308572 memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams,
8573 sizeof (tSirGtkOffloadParams));
8574 status = sme_SetGTKOffload(hHal, &hddGtkOffloadReqParams,
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308575 pAdapter->sessionId);
8576
8577 if (eHAL_STATUS_SUCCESS != status)
8578 {
8579 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8580 "%s: sme_SetGTKOffload failed, returned %d",
8581 __func__, status);
8582 return status;
8583 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308584 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8585 "%s: sme_SetGTKOffload successfull", __func__);
8586 }
8587 else
8588 {
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308589 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8590 "%s: wlan not suspended GTKOffload request is stored",
8591 __func__);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308592 }
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308593
8594 return eHAL_STATUS_SUCCESS;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308595}
8596#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
8597
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05308598/*
8599 * FUNCTION: wlan_hdd_cfg80211_set_mac_acl
8600 * This function is used to set access control policy
8601 */
8602static int wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
8603 struct net_device *dev, const struct cfg80211_acl_data *params)
8604{
8605 int i;
8606 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8607 hdd_hostapd_state_t *pHostapdState;
8608 tsap_Config_t *pConfig;
8609 v_CONTEXT_t pVosContext = NULL;
8610 hdd_context_t *pHddCtx;
8611 int status;
8612
8613 ENTER();
8614
8615 if (NULL == pAdapter)
8616 {
8617 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8618 "%s: HDD adapter is Null", __func__);
8619 return -ENODEV;
8620 }
8621
8622 if (NULL == params)
8623 {
8624 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8625 "%s: params is Null", __func__);
8626 return -EINVAL;
8627 }
8628
8629 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8630 status = wlan_hdd_validate_context(pHddCtx);
8631
8632 if (0 != status)
8633 {
8634 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8635 "%s: HDD context is not valid", __func__);
8636 return status;
8637 }
8638
8639 pVosContext = pHddCtx->pvosContext;
8640 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
8641
8642 if (NULL == pHostapdState)
8643 {
8644 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8645 "%s: pHostapdState is Null", __func__);
8646 return -EINVAL;
8647 }
8648
8649 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"acl policy: = %d"
8650 "no acl entries = %d", params->acl_policy, params->n_acl_entries);
8651
8652 if (WLAN_HDD_SOFTAP == pAdapter->device_mode)
8653 {
8654 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
8655
8656 /* default value */
8657 pConfig->num_accept_mac = 0;
8658 pConfig->num_deny_mac = 0;
8659
8660 /**
8661 * access control policy
8662 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
8663 * listed in hostapd.deny file.
8664 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
8665 * listed in hostapd.accept file.
8666 */
8667 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy)
8668 {
8669 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
8670 }
8671 else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED == params->acl_policy)
8672 {
8673 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
8674 }
8675 else
8676 {
8677 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8678 "%s:Acl Policy : %d is not supported",
8679 __func__, params->acl_policy);
8680 return -ENOTSUPP;
8681 }
8682
8683 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl)
8684 {
8685 pConfig->num_accept_mac = params->n_acl_entries;
8686 for (i = 0; i < params->n_acl_entries; i++)
8687 {
8688 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8689 "** Add ACL MAC entry %i in WhiletList :"
8690 MAC_ADDRESS_STR, i,
8691 MAC_ADDR_ARRAY(params->mac_addrs[i].addr));
8692
8693 vos_mem_copy(&pConfig->accept_mac[i], params->mac_addrs[i].addr,
8694 sizeof(qcmacaddr));
8695 }
8696 }
8697 else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl)
8698 {
8699 pConfig->num_deny_mac = params->n_acl_entries;
8700 for (i = 0; i < params->n_acl_entries; i++)
8701 {
8702 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8703 "** Add ACL MAC entry %i in BlackList :"
8704 MAC_ADDRESS_STR, i,
8705 MAC_ADDR_ARRAY(params->mac_addrs[i].addr));
8706
8707 vos_mem_copy(&pConfig->deny_mac[i], params->mac_addrs[i].addr,
8708 sizeof(qcmacaddr));
8709 }
8710 }
8711
8712 if (VOS_STATUS_SUCCESS != WLANSAP_SetMacACL(pVosContext, pConfig))
8713 {
8714 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8715 "%s: SAP Set Mac Acl fail", __func__);
8716 return -EINVAL;
8717 }
8718 }
8719 else
8720 {
8721 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8722 "%s: Invalid device_mode = %d",
8723 __func__, pAdapter->device_mode);
8724 return -EINVAL;
8725 }
8726
8727 return 0;
8728}
8729
Leo Chang9056f462013-08-01 19:21:11 -07008730#ifdef WLAN_NL80211_TESTMODE
8731#ifdef FEATURE_WLAN_LPHB
Leo Changd9df8aa2013-09-26 13:32:26 -07008732void wlan_hdd_cfg80211_lphb_ind_handler
Leo Chang9056f462013-08-01 19:21:11 -07008733(
8734 void *pAdapter,
8735 void *indCont
8736)
8737{
Leo Changd9df8aa2013-09-26 13:32:26 -07008738 tSirLPHBInd *lphbInd;
8739 struct sk_buff *skb;
Leo Chang9056f462013-08-01 19:21:11 -07008740
8741 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Leo Changd9df8aa2013-09-26 13:32:26 -07008742 "LPHB indication arrived");
Leo Chang9056f462013-08-01 19:21:11 -07008743
8744 if (NULL == indCont)
8745 {
8746 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Leo Changd9df8aa2013-09-26 13:32:26 -07008747 "LPHB IND, invalid argument");
Leo Chang9056f462013-08-01 19:21:11 -07008748 return;
8749 }
8750
Leo Changd9df8aa2013-09-26 13:32:26 -07008751 lphbInd = (tSirLPHBInd *)indCont;
Leo Chang9056f462013-08-01 19:21:11 -07008752 skb = cfg80211_testmode_alloc_event_skb(
8753 ((hdd_adapter_t *)pAdapter)->wdev.wiphy,
Leo Changd9df8aa2013-09-26 13:32:26 -07008754 sizeof(tSirLPHBInd),
Leo Chang9056f462013-08-01 19:21:11 -07008755 GFP_ATOMIC);
8756 if (!skb)
8757 {
8758 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8759 "LPHB timeout, NL buffer alloc fail");
8760 return;
8761 }
8762
Leo Changd9df8aa2013-09-26 13:32:26 -07008763 if(!nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB))
8764 {
8765 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8766 "WLAN_HDD_TM_ATTR_CMD put fail");
8767 goto nla_put_failure;
8768 }
8769 if(!nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType))
8770 {
8771 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8772 "WLAN_HDD_TM_ATTR_TYPE put fail");
8773 goto nla_put_failure;
8774 }
8775 if(!nla_put(skb, WLAN_HDD_TM_ATTR_DATA,
8776 sizeof(tSirLPHBInd), lphbInd))
8777 {
8778 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8779 "WLAN_HDD_TM_ATTR_DATA put fail");
8780 goto nla_put_failure;
8781 }
Leo Chang9056f462013-08-01 19:21:11 -07008782 cfg80211_testmode_event(skb, GFP_ATOMIC);
8783 return;
8784
8785nla_put_failure:
8786 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8787 "NLA Put fail");
8788 kfree_skb(skb);
8789
8790 return;
8791}
8792#endif /* FEATURE_WLAN_LPHB */
8793
8794static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy, void *data, int len)
8795{
8796 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
8797 int err = 0;
8798#ifdef FEATURE_WLAN_LPHB
8799 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Leo Changd9df8aa2013-09-26 13:32:26 -07008800 eHalStatus smeStatus;
Leo Chang9056f462013-08-01 19:21:11 -07008801#endif /* FEATURE_WLAN_LPHB */
8802
8803 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data, len, wlan_hdd_tm_policy);
8804 if (err)
8805 {
8806 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8807 "%s Testmode INV ATTR", __func__);
8808 return err;
8809 }
8810
8811 if (!tb[WLAN_HDD_TM_ATTR_CMD])
8812 {
8813 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8814 "%s Testmode INV CMD", __func__);
8815 return -EINVAL;
8816 }
8817
8818 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]))
8819 {
8820#ifdef FEATURE_WLAN_LPHB
8821 /* Low Power Heartbeat configuration request */
8822 case WLAN_HDD_TM_CMD_WLAN_HB:
8823 {
8824 int buf_len;
8825 void *buf;
8826 tSirLPHBReq *hb_params = NULL;
8827
8828 if (!tb[WLAN_HDD_TM_ATTR_DATA])
8829 {
8830 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8831 "%s Testmode INV DATA", __func__);
8832 return -EINVAL;
8833 }
8834
8835 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
8836 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
8837 hb_params = (tSirLPHBReq *)vos_mem_malloc(sizeof(tSirLPHBReq));
8838 if (NULL == hb_params)
8839 {
8840 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8841 "%s Request Buffer Alloc Fail", __func__);
8842 return -EINVAL;
8843 }
8844
8845 vos_mem_copy(hb_params, buf, buf_len);
Leo Changd9df8aa2013-09-26 13:32:26 -07008846 smeStatus = sme_LPHBConfigReq((tHalHandle)(pHddCtx->hHal),
8847 hb_params,
8848 wlan_hdd_cfg80211_lphb_ind_handler);
8849 if (eHAL_STATUS_SUCCESS != smeStatus)
Leo Chang9056f462013-08-01 19:21:11 -07008850 {
Leo Changd9df8aa2013-09-26 13:32:26 -07008851 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8852 "LPHB Config Fail, disable");
Leo Chang9056f462013-08-01 19:21:11 -07008853 vos_mem_free(hb_params);
8854 }
Leo Chang9056f462013-08-01 19:21:11 -07008855 return 0;
8856 }
8857#endif /* FEATURE_WLAN_LPHB */
8858 default:
8859 return -EOPNOTSUPP;
8860 }
8861
8862 return err;
8863}
8864#endif /* CONFIG_NL80211_TESTMODE */
8865
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308866static int wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy,
8867 struct net_device *dev,
8868 int idx, struct survey_info *survey)
8869{
8870 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8871 hdd_context_t *pHddCtx;
Mihir Sheted9072e02013-08-21 17:02:29 +05308872 hdd_station_ctx_t *pHddStaCtx;
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308873 tHalHandle halHandle;
Mihir Sheted9072e02013-08-21 17:02:29 +05308874 v_U32_t channel = 0, freq = 0; /* Initialization Required */
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308875 v_S7_t snr,rssi;
8876 int status, i, j, filled = 0;
8877
8878 ENTER();
8879
8880
8881 if (NULL == pAdapter)
8882 {
8883 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8884 "%s: HDD adapter is Null", __func__);
8885 return -ENODEV;
8886 }
8887
8888 if (NULL == wiphy)
8889 {
8890 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8891 "%s: wiphy is Null", __func__);
8892 return -ENODEV;
8893 }
8894
8895 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8896 status = wlan_hdd_validate_context(pHddCtx);
8897
8898 if (0 != status)
8899 {
8900 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8901 "%s: HDD context is not valid", __func__);
8902 return status;
8903 }
8904
Mihir Sheted9072e02013-08-21 17:02:29 +05308905 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8906
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308907 if (0 == pHddCtx->cfg_ini->fEnableSNRMonitoring ||
Mihir Sheted9072e02013-08-21 17:02:29 +05308908 0 != pAdapter->survey_idx ||
8909 eConnectionState_Associated != pHddStaCtx->conn_info.connState)
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308910 {
8911 /* The survey dump ops when implemented completely is expected to
8912 * return a survey of all channels and the ops is called by the
8913 * kernel with incremental values of the argument 'idx' till it
8914 * returns -ENONET. But we can only support the survey for the
8915 * operating channel for now. survey_idx is used to track
8916 * that the ops is called only once and then return -ENONET for
8917 * the next iteration
8918 */
8919 pAdapter->survey_idx = 0;
8920 return -ENONET;
8921 }
8922
8923 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
8924
8925 wlan_hdd_get_snr(pAdapter, &snr);
8926 wlan_hdd_get_rssi(pAdapter, &rssi);
8927
8928 sme_GetOperationChannel(halHandle, &channel, pAdapter->sessionId);
8929 hdd_wlan_get_freq(channel, &freq);
8930
8931
8932 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
8933 {
8934 if (NULL == wiphy->bands[i])
8935 {
8936 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
8937 "%s: wiphy->bands[i] is NULL, i = %d", __func__, i);
8938 continue;
8939 }
8940
8941 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
8942 {
8943 struct ieee80211_supported_band *band = wiphy->bands[i];
8944
8945 if (band->channels[j].center_freq == (v_U16_t)freq)
8946 {
8947 survey->channel = &band->channels[j];
8948 /* The Rx BDs contain SNR values in dB for the received frames
8949 * while the supplicant expects noise. So we calculate and
8950 * return the value of noise (dBm)
8951 * SNR (dB) = RSSI (dBm) - NOISE (dBm)
8952 */
8953 survey->noise = rssi - snr;
8954 survey->filled = SURVEY_INFO_NOISE_DBM;
8955 filled = 1;
8956 }
8957 }
8958 }
8959
8960 if (filled)
8961 pAdapter->survey_idx = 1;
8962 else
8963 {
8964 pAdapter->survey_idx = 0;
8965 return -ENONET;
8966 }
8967
8968 return 0;
8969}
8970
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308971/*
8972 * FUNCTION: wlan_hdd_cfg80211_resume_wlan
8973 * this is called when cfg80211 driver resume
8974 * driver updates latest sched_scan scan result(if any) to cfg80211 database
8975 */
8976int wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
8977{
8978 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8979 hdd_adapter_t *pAdapter;
8980 hdd_adapter_list_node_t *pAdapterNode, *pNext;
8981 VOS_STATUS status = VOS_STATUS_SUCCESS;
8982
8983 ENTER();
8984
8985 if ( NULL == pHddCtx )
8986 {
8987 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8988 "%s: HddCtx validation failed", __func__);
8989 return 0;
8990 }
8991
8992 if (pHddCtx->isLogpInProgress)
8993 {
8994 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8995 "%s: LOGP in Progress. Ignore!!!", __func__);
8996 return 0;
8997 }
8998
8999 if (pHddCtx->isLoadUnloadInProgress)
9000 {
9001 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9002 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
9003 return 0;
9004 }
9005
9006 spin_lock(&pHddCtx->schedScan_lock);
9007 pHddCtx->isWiphySuspended = FALSE;
9008 if (TRUE != pHddCtx->isSchedScanUpdatePending)
9009 {
9010 spin_unlock(&pHddCtx->schedScan_lock);
9011 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9012 "%s: Return resume is not due to PNO indication", __func__);
9013 return 0;
9014 }
9015 // Reset flag to avoid updatating cfg80211 data old results again
9016 pHddCtx->isSchedScanUpdatePending = FALSE;
9017 spin_unlock(&pHddCtx->schedScan_lock);
9018
9019 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9020
9021 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9022 {
9023 pAdapter = pAdapterNode->pAdapter;
9024 if ( (NULL != pAdapter) &&
9025 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
9026 {
9027 if (0 != wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter))
9028 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
9029 "%s: NO SCAN result", __func__);
9030 else
9031 cfg80211_sched_scan_results(pHddCtx->wiphy);
9032
9033 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9034 "%s : cfg80211 scan result database updated", __func__);
9035
9036 return 0;
9037
9038 }
9039 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9040 pAdapterNode = pNext;
9041 }
9042
9043 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9044 "%s: Failed to find Adapter", __func__);
9045 return 0;
9046}
9047
9048/*
9049 * FUNCTION: wlan_hdd_cfg80211_suspend_wlan
9050 * this is called when cfg80211 driver suspends
9051 */
9052int wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
9053 struct cfg80211_wowlan *wow)
9054{
9055 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9056
9057 ENTER();
9058 if (NULL == pHddCtx)
9059 {
9060 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9061 "%s: HddCtx validation failed", __func__);
9062 return 0;
9063 }
9064
9065 pHddCtx->isWiphySuspended = TRUE;
9066
9067 EXIT();
9068
9069 return 0;
9070}
9071
Jeff Johnson295189b2012-06-20 16:38:30 -07009072/* cfg80211_ops */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309073static struct cfg80211_ops wlan_hdd_cfg80211_ops =
Jeff Johnson295189b2012-06-20 16:38:30 -07009074{
9075 .add_virtual_intf = wlan_hdd_add_virtual_intf,
9076 .del_virtual_intf = wlan_hdd_del_virtual_intf,
9077 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
9078 .change_station = wlan_hdd_change_station,
9079#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
9080 .add_beacon = wlan_hdd_cfg80211_add_beacon,
9081 .del_beacon = wlan_hdd_cfg80211_del_beacon,
9082 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07009083#else
9084 .start_ap = wlan_hdd_cfg80211_start_ap,
9085 .change_beacon = wlan_hdd_cfg80211_change_beacon,
9086 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07009087#endif
9088 .change_bss = wlan_hdd_cfg80211_change_bss,
9089 .add_key = wlan_hdd_cfg80211_add_key,
9090 .get_key = wlan_hdd_cfg80211_get_key,
9091 .del_key = wlan_hdd_cfg80211_del_key,
9092 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08009093#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07009094 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08009095#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009096 .scan = wlan_hdd_cfg80211_scan,
9097 .connect = wlan_hdd_cfg80211_connect,
9098 .disconnect = wlan_hdd_cfg80211_disconnect,
9099 .join_ibss = wlan_hdd_cfg80211_join_ibss,
9100 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
9101 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
9102 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
9103 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
Jeff Johnson295189b2012-06-20 16:38:30 -07009104 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
9105 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
9106 .mgmt_tx = wlan_hdd_action,
9107#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
9108 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
9109 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
9110 .set_txq_params = wlan_hdd_set_txq_params,
9111#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009112 .get_station = wlan_hdd_cfg80211_get_station,
9113 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
9114 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07009115 .add_station = wlan_hdd_cfg80211_add_station,
9116#ifdef FEATURE_WLAN_LFR
9117 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
9118 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
9119 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
9120#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07009121#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
9122 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
9123#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08009124#ifdef FEATURE_WLAN_TDLS
9125 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
9126 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
9127#endif
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309128#ifdef WLAN_FEATURE_GTK_OFFLOAD
9129 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
9130#endif /* WLAN_FEATURE_GTK_OFFLOAD */
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05309131#ifdef FEATURE_WLAN_SCAN_PNO
9132 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
9133 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
9134#endif /*FEATURE_WLAN_SCAN_PNO */
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05309135 .resume = wlan_hdd_cfg80211_resume_wlan,
9136 .suspend = wlan_hdd_cfg80211_suspend_wlan,
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05309137 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
Leo Chang9056f462013-08-01 19:21:11 -07009138#ifdef WLAN_NL80211_TESTMODE
9139 .testmode_cmd = wlan_hdd_cfg80211_testmode,
9140#endif
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05309141 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Jeff Johnson295189b2012-06-20 16:38:30 -07009142};
9143