blob: 91538cf13b46741e66f0aa3b3f97b5db6e87c331 [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"
Mohit Khanna698ba2a2012-12-04 15:08:18 -080087#endif
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +053088#include "wlan_nv.h"
Leo Chang6fe1f922013-06-07 19:21:24 -070089#include "wlan_hdd_dev_pwr.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070090
91#define g_mode_rates_size (12)
92#define a_mode_rates_size (8)
93#define FREQ_BASE_80211G (2407)
94#define FREQ_BAND_DIFF_80211G (5)
Jeff Johnson04dd8a82012-06-29 20:41:40 -070095#define MAX_SCAN_SSID 9
Jeff Johnson295189b2012-06-20 16:38:30 -070096#define GET_IE_LEN_IN_BSS_DESC(lenInBss) ( lenInBss + sizeof(lenInBss) - \
97 ((int) OFFSET_OF( tSirBssDescription, ieFields)))
98
99#define HDD2GHZCHAN(freq, chan, flag) { \
100 .band = IEEE80211_BAND_2GHZ, \
101 .center_freq = (freq), \
102 .hw_value = (chan),\
103 .flags = (flag), \
104 .max_antenna_gain = 0 ,\
105 .max_power = 30, \
106}
107
108#define HDD5GHZCHAN(freq, chan, flag) { \
109 .band = IEEE80211_BAND_5GHZ, \
110 .center_freq = (freq), \
111 .hw_value = (chan),\
112 .flags = (flag), \
113 .max_antenna_gain = 0 ,\
114 .max_power = 30, \
115}
116
117#define HDD_G_MODE_RATETAB(rate, rate_id, flag)\
118{\
119 .bitrate = rate, \
120 .hw_value = rate_id, \
121 .flags = flag, \
122}
123
Lee Hoonkic1262f22013-01-24 21:59:00 -0800124#ifndef WLAN_FEATURE_TDLS_DEBUG
125#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_INFO
126#else
127#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_ERROR
128#endif
129
Gopichand Nakkala356fb102013-03-06 12:34:04 +0530130#ifdef WLAN_FEATURE_VOWIFI_11R
131#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
132#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
133#endif
134
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530135static const u32 hdd_cipher_suites[] =
Jeff Johnson295189b2012-06-20 16:38:30 -0700136{
137 WLAN_CIPHER_SUITE_WEP40,
138 WLAN_CIPHER_SUITE_WEP104,
139 WLAN_CIPHER_SUITE_TKIP,
140#ifdef FEATURE_WLAN_CCX
141#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
142 WLAN_CIPHER_SUITE_KRK,
143 WLAN_CIPHER_SUITE_CCMP,
144#else
145 WLAN_CIPHER_SUITE_CCMP,
146#endif
147#ifdef FEATURE_WLAN_WAPI
148 WLAN_CIPHER_SUITE_SMS4,
149#endif
Chet Lanctot186b5732013-03-18 10:26:30 -0700150#ifdef WLAN_FEATURE_11W
151 WLAN_CIPHER_SUITE_AES_CMAC,
152#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700153};
154
155static inline int is_broadcast_ether_addr(const u8 *addr)
156{
157 return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&
158 (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
159}
160
161static struct ieee80211_channel hdd_channels_2_4_GHZ[] =
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530162{
Jeff Johnson295189b2012-06-20 16:38:30 -0700163 HDD2GHZCHAN(2412, 1, 0) ,
164 HDD2GHZCHAN(2417, 2, 0) ,
165 HDD2GHZCHAN(2422, 3, 0) ,
166 HDD2GHZCHAN(2427, 4, 0) ,
167 HDD2GHZCHAN(2432, 5, 0) ,
168 HDD2GHZCHAN(2437, 6, 0) ,
169 HDD2GHZCHAN(2442, 7, 0) ,
170 HDD2GHZCHAN(2447, 8, 0) ,
171 HDD2GHZCHAN(2452, 9, 0) ,
172 HDD2GHZCHAN(2457, 10, 0) ,
173 HDD2GHZCHAN(2462, 11, 0) ,
174 HDD2GHZCHAN(2467, 12, 0) ,
175 HDD2GHZCHAN(2472, 13, 0) ,
176 HDD2GHZCHAN(2484, 14, 0) ,
177};
178
Jeff Johnson295189b2012-06-20 16:38:30 -0700179static struct ieee80211_channel hdd_social_channels_2_4_GHZ[] =
180{
181 HDD2GHZCHAN(2412, 1, 0) ,
182 HDD2GHZCHAN(2437, 6, 0) ,
183 HDD2GHZCHAN(2462, 11, 0) ,
184};
Jeff Johnson295189b2012-06-20 16:38:30 -0700185
186static struct ieee80211_channel hdd_channels_5_GHZ[] =
187{
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700188 HDD5GHZCHAN(4920, 240, 0) ,
189 HDD5GHZCHAN(4940, 244, 0) ,
190 HDD5GHZCHAN(4960, 248, 0) ,
191 HDD5GHZCHAN(4980, 252, 0) ,
192 HDD5GHZCHAN(5040, 208, 0) ,
193 HDD5GHZCHAN(5060, 212, 0) ,
194 HDD5GHZCHAN(5080, 216, 0) ,
Jeff Johnson295189b2012-06-20 16:38:30 -0700195 HDD5GHZCHAN(5180, 36, 0) ,
196 HDD5GHZCHAN(5200, 40, 0) ,
197 HDD5GHZCHAN(5220, 44, 0) ,
198 HDD5GHZCHAN(5240, 48, 0) ,
199 HDD5GHZCHAN(5260, 52, 0) ,
200 HDD5GHZCHAN(5280, 56, 0) ,
201 HDD5GHZCHAN(5300, 60, 0) ,
202 HDD5GHZCHAN(5320, 64, 0) ,
203 HDD5GHZCHAN(5500,100, 0) ,
204 HDD5GHZCHAN(5520,104, 0) ,
205 HDD5GHZCHAN(5540,108, 0) ,
206 HDD5GHZCHAN(5560,112, 0) ,
207 HDD5GHZCHAN(5580,116, 0) ,
208 HDD5GHZCHAN(5600,120, 0) ,
209 HDD5GHZCHAN(5620,124, 0) ,
210 HDD5GHZCHAN(5640,128, 0) ,
211 HDD5GHZCHAN(5660,132, 0) ,
212 HDD5GHZCHAN(5680,136, 0) ,
213 HDD5GHZCHAN(5700,140, 0) ,
214 HDD5GHZCHAN(5745,149, 0) ,
215 HDD5GHZCHAN(5765,153, 0) ,
216 HDD5GHZCHAN(5785,157, 0) ,
217 HDD5GHZCHAN(5805,161, 0) ,
218 HDD5GHZCHAN(5825,165, 0) ,
219};
220
221static struct ieee80211_rate g_mode_rates[] =
222{
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530223 HDD_G_MODE_RATETAB(10, 0x1, 0),
224 HDD_G_MODE_RATETAB(20, 0x2, 0),
225 HDD_G_MODE_RATETAB(55, 0x4, 0),
226 HDD_G_MODE_RATETAB(110, 0x8, 0),
227 HDD_G_MODE_RATETAB(60, 0x10, 0),
228 HDD_G_MODE_RATETAB(90, 0x20, 0),
229 HDD_G_MODE_RATETAB(120, 0x40, 0),
230 HDD_G_MODE_RATETAB(180, 0x80, 0),
231 HDD_G_MODE_RATETAB(240, 0x100, 0),
232 HDD_G_MODE_RATETAB(360, 0x200, 0),
233 HDD_G_MODE_RATETAB(480, 0x400, 0),
Jeff Johnson295189b2012-06-20 16:38:30 -0700234 HDD_G_MODE_RATETAB(540, 0x800, 0),
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530235};
Jeff Johnson295189b2012-06-20 16:38:30 -0700236
237static struct ieee80211_rate a_mode_rates[] =
238{
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530239 HDD_G_MODE_RATETAB(60, 0x10, 0),
240 HDD_G_MODE_RATETAB(90, 0x20, 0),
241 HDD_G_MODE_RATETAB(120, 0x40, 0),
242 HDD_G_MODE_RATETAB(180, 0x80, 0),
243 HDD_G_MODE_RATETAB(240, 0x100, 0),
244 HDD_G_MODE_RATETAB(360, 0x200, 0),
245 HDD_G_MODE_RATETAB(480, 0x400, 0),
Jeff Johnson295189b2012-06-20 16:38:30 -0700246 HDD_G_MODE_RATETAB(540, 0x800, 0),
247};
248
249static struct ieee80211_supported_band wlan_hdd_band_2_4_GHZ =
250{
251 .channels = hdd_channels_2_4_GHZ,
252 .n_channels = ARRAY_SIZE(hdd_channels_2_4_GHZ),
253 .band = IEEE80211_BAND_2GHZ,
254 .bitrates = g_mode_rates,
255 .n_bitrates = g_mode_rates_size,
256 .ht_cap.ht_supported = 1,
257 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
258 | IEEE80211_HT_CAP_GRN_FLD
259 | IEEE80211_HT_CAP_DSSSCCK40
260 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
261 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
262 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
263 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
264 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
265 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
266};
267
Jeff Johnson295189b2012-06-20 16:38:30 -0700268static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_GHZ =
269{
270 .channels = hdd_social_channels_2_4_GHZ,
271 .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_GHZ),
272 .band = IEEE80211_BAND_2GHZ,
273 .bitrates = g_mode_rates,
274 .n_bitrates = g_mode_rates_size,
275 .ht_cap.ht_supported = 1,
276 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
277 | IEEE80211_HT_CAP_GRN_FLD
278 | IEEE80211_HT_CAP_DSSSCCK40
279 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
280 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
281 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
282 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
283 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
284 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
285};
Jeff Johnson295189b2012-06-20 16:38:30 -0700286
287static struct ieee80211_supported_band wlan_hdd_band_5_GHZ =
288{
289 .channels = hdd_channels_5_GHZ,
290 .n_channels = ARRAY_SIZE(hdd_channels_5_GHZ),
291 .band = IEEE80211_BAND_5GHZ,
292 .bitrates = a_mode_rates,
293 .n_bitrates = a_mode_rates_size,
294 .ht_cap.ht_supported = 1,
295 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
296 | IEEE80211_HT_CAP_GRN_FLD
297 | IEEE80211_HT_CAP_DSSSCCK40
298 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
299 | IEEE80211_HT_CAP_SGI_40
300 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
301 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
302 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
303 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
304 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
305 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
306};
307
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530308/* This structure contain information what kind of frame are expected in
Jeff Johnson295189b2012-06-20 16:38:30 -0700309 TX/RX direction for each kind of interface */
310static const struct ieee80211_txrx_stypes
311wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
312 [NL80211_IFTYPE_STATION] = {
313 .tx = 0xffff,
314 .rx = BIT(SIR_MAC_MGMT_ACTION) |
315 BIT(SIR_MAC_MGMT_PROBE_REQ),
316 },
317 [NL80211_IFTYPE_AP] = {
318 .tx = 0xffff,
319 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
320 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
321 BIT(SIR_MAC_MGMT_PROBE_REQ) |
322 BIT(SIR_MAC_MGMT_DISASSOC) |
323 BIT(SIR_MAC_MGMT_AUTH) |
324 BIT(SIR_MAC_MGMT_DEAUTH) |
325 BIT(SIR_MAC_MGMT_ACTION),
326 },
Jeff Johnsonbc006202013-04-29 14:05:30 -0700327 [NL80211_IFTYPE_ADHOC] = {
328 .tx = 0xffff,
329 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
330 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
331 BIT(SIR_MAC_MGMT_PROBE_REQ) |
332 BIT(SIR_MAC_MGMT_DISASSOC) |
333 BIT(SIR_MAC_MGMT_AUTH) |
334 BIT(SIR_MAC_MGMT_DEAUTH) |
335 BIT(SIR_MAC_MGMT_ACTION),
336 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700337 [NL80211_IFTYPE_P2P_CLIENT] = {
338 .tx = 0xffff,
339 .rx = BIT(SIR_MAC_MGMT_ACTION) |
340 BIT(SIR_MAC_MGMT_PROBE_REQ),
341 },
342 [NL80211_IFTYPE_P2P_GO] = {
343 /* This is also same as for SoftAP */
344 .tx = 0xffff,
345 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
346 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
347 BIT(SIR_MAC_MGMT_PROBE_REQ) |
348 BIT(SIR_MAC_MGMT_DISASSOC) |
349 BIT(SIR_MAC_MGMT_AUTH) |
350 BIT(SIR_MAC_MGMT_DEAUTH) |
351 BIT(SIR_MAC_MGMT_ACTION),
352 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700353};
354
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800355#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800356static const struct ieee80211_iface_limit
357wlan_hdd_iface_limit[] = {
358 {
Sunil Ravia72c3992013-01-31 06:12:22 -0800359 /* max = 3 ; Our driver create two interfaces during driver init
360 * wlan0 and p2p0 interfaces. p2p0 is considered as station
361 * interface until a group is formed. In JB architecture, once the
362 * group is formed, interface type of p2p0 is changed to P2P GO or
363 * Client.
364 * When supplicant remove the group, it first issue a set interface
365 * cmd to change the mode back to Station. In JB this works fine as
366 * we advertize two station type interface during driver init.
367 * Some vendors create separate interface for P2P GO/Client,
368 * after group formation(Third one). But while group remove
369 * supplicant first tries to change the mode(3rd interface) to STATION
370 * But as we advertized only two sta type interfaces nl80211 was
371 * returning error for the third one which was leading to failure in
372 * delete interface. Ideally while removing the group, supplicant
373 * should not try to change the 3rd interface mode to Station type.
374 * Till we get a fix in wpa_supplicant, we advertize max STA
375 * interface type to 3
376 */
377 .max = 3,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800378 .types = BIT(NL80211_IFTYPE_STATION),
379 },
380 {
381 .max = 1,
Jeff Johnsonbc006202013-04-29 14:05:30 -0700382 .types = BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP),
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800383 },
384 {
385 .max = 1,
386 .types = BIT(NL80211_IFTYPE_P2P_GO) |
387 BIT(NL80211_IFTYPE_P2P_CLIENT),
388 },
389};
390
391/* By default, only single channel concurrency is allowed */
392static struct ieee80211_iface_combination
393wlan_hdd_iface_combination = {
394 .limits = wlan_hdd_iface_limit,
395 .num_different_channels = 1,
Sunil Ravia72c3992013-01-31 06:12:22 -0800396 /*
397 * max = WLAN_MAX_INTERFACES ; JellyBean architecture creates wlan0
398 * and p2p0 interfaces during driver init
399 * Some vendors create separate interface for P2P operations.
400 * wlan0: STA interface
401 * p2p0: P2P Device interface, action frames goes
402 * through this interface.
403 * p2p-xx: P2P interface, After GO negotiation this interface is
404 * created for p2p operations(GO/CLIENT interface).
405 */
406 .max_interfaces = WLAN_MAX_INTERFACES,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800407 .n_limits = ARRAY_SIZE(wlan_hdd_iface_limit),
408 .beacon_int_infra_match = false,
409};
410#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800411
Jeff Johnson295189b2012-06-20 16:38:30 -0700412static struct cfg80211_ops wlan_hdd_cfg80211_ops;
413
414/* Data rate 100KBPS based on IE Index */
415struct index_data_rate_type
416{
417 v_U8_t beacon_rate_index;
418 v_U16_t supported_rate[4];
419};
420
421/* 11B, 11G Rate table include Basic rate and Extended rate
422 The IDX field is the rate index
423 The HI field is the rate when RSSI is strong or being ignored
424 (in this case we report actual rate)
425 The MID field is the rate when RSSI is moderate
426 (in this case we cap 11b rates at 5.5 and 11g rates at 24)
427 The LO field is the rate when RSSI is low
428 (in this case we don't report rates, actual current rate used)
429 */
430static const struct
431{
432 v_U8_t beacon_rate_index;
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700433 v_U16_t supported_rate[4];
Jeff Johnson295189b2012-06-20 16:38:30 -0700434} supported_data_rate[] =
435{
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700436/* IDX HI HM LM LO (RSSI-based index */
437 {2, { 10, 10, 10, 0}},
438 {4, { 20, 20, 10, 0}},
439 {11, { 55, 20, 10, 0}},
440 {12, { 60, 55, 20, 0}},
441 {18, { 90, 55, 20, 0}},
442 {22, {110, 55, 20, 0}},
443 {24, {120, 90, 60, 0}},
444 {36, {180, 120, 60, 0}},
445 {44, {220, 180, 60, 0}},
446 {48, {240, 180, 90, 0}},
447 {66, {330, 180, 90, 0}},
448 {72, {360, 240, 90, 0}},
449 {96, {480, 240, 120, 0}},
450 {108, {540, 240, 120, 0}}
Jeff Johnson295189b2012-06-20 16:38:30 -0700451};
452
453/* MCS Based rate table */
454static struct index_data_rate_type supported_mcs_rate[] =
455{
456/* MCS L20 L40 S20 S40 */
457 {0, {65, 135, 72, 150}},
458 {1, {130, 270, 144, 300}},
459 {2, {195, 405, 217, 450}},
460 {3, {260, 540, 289, 600}},
461 {4, {390, 810, 433, 900}},
462 {5, {520, 1080, 578, 1200}},
463 {6, {585, 1215, 650, 1350}},
464 {7, {650, 1350, 722, 1500}}
465};
466
Leo Chang6f8870f2013-03-26 18:11:36 -0700467#ifdef WLAN_FEATURE_11AC
468
Gopichand Nakkala4c705372013-04-24 13:20:33 +0530469#define DATA_RATE_11AC_MCS_MASK 0x03
Leo Chang6f8870f2013-03-26 18:11:36 -0700470
471struct index_vht_data_rate_type
472{
473 v_U8_t beacon_rate_index;
Gopichand Nakkala4c705372013-04-24 13:20:33 +0530474 v_U16_t supported_VHT80_rate[2];
475 v_U16_t supported_VHT40_rate[2];
476 v_U16_t supported_VHT20_rate[2];
Leo Chang6f8870f2013-03-26 18:11:36 -0700477};
478
479typedef enum
480{
481 DATA_RATE_11AC_MAX_MCS_7,
482 DATA_RATE_11AC_MAX_MCS_8,
483 DATA_RATE_11AC_MAX_MCS_9,
484 DATA_RATE_11AC_MAX_MCS_NA
485} eDataRate11ACMaxMcs;
486
487/* MCS Based VHT rate table */
488static struct index_vht_data_rate_type supported_vht_mcs_rate[] =
489{
Gopichand Nakkala4c705372013-04-24 13:20:33 +0530490/* MCS L80 S80 L40 S40 L20 S40*/
491 {0, {293, 325}, {135, 150}, {65, 72}},
492 {1, {585, 650}, {270, 300}, {130, 144}},
493 {2, {878, 975}, {405, 450}, {195, 217}},
494 {3, {1170, 1300}, {540, 600}, {260, 289}},
495 {4, {1755, 1950}, {810, 900}, {390, 433}},
496 {5, {2340, 2600}, {1080, 1200}, {520, 578}},
497 {6, {2633, 2925}, {1215, 1350}, {585, 650}},
498 {7, {2925, 3250}, {1350, 1500}, {650, 722}},
499 {8, {3510, 3900}, {1620, 1800}, {780, 867}},
500 {9, {3900, 4333}, {1800, 2000}, {780, 867}}
Leo Chang6f8870f2013-03-26 18:11:36 -0700501};
502#endif /* WLAN_FEATURE_11AC */
503
Jeff Johnson295189b2012-06-20 16:38:30 -0700504extern struct net_device_ops net_ops_struct;
505
Leo Chang9056f462013-08-01 19:21:11 -0700506#ifdef WLAN_NL80211_TESTMODE
507enum wlan_hdd_tm_attr
508{
509 WLAN_HDD_TM_ATTR_INVALID = 0,
510 WLAN_HDD_TM_ATTR_CMD = 1,
511 WLAN_HDD_TM_ATTR_DATA = 2,
512 WLAN_HDD_TM_ATTR_TYPE = 3,
513 /* keep last */
514 WLAN_HDD_TM_ATTR_AFTER_LAST,
515 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
516};
517
518enum wlan_hdd_tm_cmd
519{
520 WLAN_HDD_TM_CMD_WLAN_HB = 1,
521};
522
523#define WLAN_HDD_TM_DATA_MAX_LEN 5000
524
525static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] =
526{
527 [WLAN_HDD_TM_ATTR_CMD] = { .type = NLA_U32 },
528 [WLAN_HDD_TM_ATTR_DATA] = { .type = NLA_BINARY,
529 .len = WLAN_HDD_TM_DATA_MAX_LEN },
530};
531#endif /* WLAN_NL80211_TESTMODE */
532
Jeff Johnson295189b2012-06-20 16:38:30 -0700533/*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530534 * FUNCTION: wlan_hdd_cfg80211_wiphy_alloc
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530535 * This function is called by hdd_wlan_startup()
536 * during initialization.
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530537 * This function is used to allocate wiphy structure.
Jeff Johnson295189b2012-06-20 16:38:30 -0700538 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530539struct wiphy *wlan_hdd_cfg80211_wiphy_alloc(int priv_size)
Jeff Johnson295189b2012-06-20 16:38:30 -0700540{
541 struct wiphy *wiphy;
542 ENTER();
543
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530544 /*
545 * Create wiphy device
Jeff Johnson295189b2012-06-20 16:38:30 -0700546 */
547 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
548
549 if (!wiphy)
550 {
551 /* Print error and jump into err label and free the memory */
552 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__);
553 return NULL;
554 }
555
556 return wiphy;
557}
558
559/*
560 * FUNCTION: wlan_hdd_cfg80211_update_band
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530561 * This function is called from the supplicant through a
Jeff Johnson295189b2012-06-20 16:38:30 -0700562 * private ioctl to change the band value
563 */
564int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
565{
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530566 int i, j;
567 eNVChannelEnabledType channelEnabledState;
568
Jeff Johnsone7245742012-09-05 17:12:55 -0700569 ENTER();
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530570 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
Jeff Johnson295189b2012-06-20 16:38:30 -0700571 {
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530572
573 if (NULL == wiphy->bands[i])
574 {
575 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[i] is NULL, i = %d",
576 __func__, i);
577 continue;
578 }
579
580 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
581 {
582 struct ieee80211_supported_band *band = wiphy->bands[i];
583
584 channelEnabledState = vos_nv_getChannelEnabledState(
585 band->channels[j].hw_value);
586
587 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) // 5G only
588 {
589 // Enable Social channels for P2P
590 if (WLAN_HDD_IS_SOCIAL_CHANNEL(band->channels[j].center_freq) &&
591 NV_CHANNEL_ENABLE == channelEnabledState)
592 band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED;
593 else
594 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
595 continue;
596 }
597 else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == eBand) // 2G only
598 {
599 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
600 continue;
601 }
602
603 if (NV_CHANNEL_DISABLE == channelEnabledState ||
604 NV_CHANNEL_INVALID == channelEnabledState)
605 {
606 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
607 }
608 else if (NV_CHANNEL_DFS == channelEnabledState)
609 {
610 band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED;
611 band->channels[j].flags |= IEEE80211_CHAN_RADAR;
612 }
613 else
614 {
615 band->channels[j].flags &= ~(IEEE80211_CHAN_DISABLED
616 |IEEE80211_CHAN_RADAR);
617 }
618 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700619 }
620 return 0;
621}
622/*
623 * FUNCTION: wlan_hdd_cfg80211_init
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530624 * This function is called by hdd_wlan_startup()
625 * during initialization.
Jeff Johnson295189b2012-06-20 16:38:30 -0700626 * This function is used to initialize and register wiphy structure.
627 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530628int wlan_hdd_cfg80211_init(struct device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700629 struct wiphy *wiphy,
630 hdd_config_t *pCfg
631 )
632{
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530633 int i, j;
Jeff Johnsone7245742012-09-05 17:12:55 -0700634 ENTER();
635
Jeff Johnson295189b2012-06-20 16:38:30 -0700636 /* Now bind the underlying wlan device with wiphy */
637 set_wiphy_dev(wiphy, dev);
638
639 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
Amar Singhalfddc28c2013-09-05 13:03:40 -0700640
641 /* This will disable updating of NL channels from passive to
642 * active if a beacon is received on passive channel. */
643 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
644 wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
645
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700646#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700647 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
648 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
649 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
Jeff Johnsone7245742012-09-05 17:12:55 -0700650 | WIPHY_FLAG_OFFCHAN_TX;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700651#endif
Srinivas Girigowda640728a2013-03-28 12:21:54 -0700652#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
653 if (pCfg->isFastTransitionEnabled
James Zmuda77fb5ae2013-01-29 08:00:17 -0800654#ifdef FEATURE_WLAN_LFR
Srinivas Girigowda640728a2013-03-28 12:21:54 -0700655 || pCfg->isFastRoamIniFeatureEnabled
656#endif
657#ifdef FEATURE_WLAN_CCX
658 || pCfg->isCcxIniFeatureEnabled
659#endif
660 )
661 {
662 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
663 }
James Zmuda77fb5ae2013-01-29 08:00:17 -0800664#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800665#ifdef FEATURE_WLAN_TDLS
666 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
667 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
668#endif
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +0530669#ifdef FEATURE_WLAN_SCAN_PNO
670 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
671 wiphy->max_sched_scan_ssids = MAX_SCAN_SSID;
672 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
673#endif/*FEATURE_WLAN_SCAN_PNO*/
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800674
Amar Singhalfddc28c2013-09-05 13:03:40 -0700675#ifdef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700676 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
677 driver can still register regulatory callback and
Amar Singhalfddc28c2013-09-05 13:03:40 -0700678 it will get regulatory settings in wiphy->band[], but
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700679 driver need to determine what to do with both
680 regulatory settings */
Amar Singhalfddc28c2013-09-05 13:03:40 -0700681
682 wiphy->reg_notifier = wlan_hdd_linux_reg_notifier;
683#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700684
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530685 wiphy->max_scan_ssids = MAX_SCAN_SSID;
686
Madan Mohan Koyyalamudi6815b162013-07-19 17:17:46 +0530687 wiphy->max_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Jeff Johnson295189b2012-06-20 16:38:30 -0700688
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +0530689 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
690
Jeff Johnson295189b2012-06-20 16:38:30 -0700691 /* Supports STATION & AD-HOC modes right now */
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530692 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -0700693 | BIT(NL80211_IFTYPE_ADHOC)
Jeff Johnson295189b2012-06-20 16:38:30 -0700694 | BIT(NL80211_IFTYPE_P2P_CLIENT)
695 | BIT(NL80211_IFTYPE_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -0700696 | BIT(NL80211_IFTYPE_AP);
697
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800698#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800699 if( pCfg->enableMCC )
700 {
701 /* Currently, supports up to two channels */
702 wlan_hdd_iface_combination.num_different_channels = 2;
703
704 if( !pCfg->allowMCCGODiffBI )
705 wlan_hdd_iface_combination.beacon_int_infra_match = true;
706
707 }
708 wiphy->iface_combinations = &wlan_hdd_iface_combination;
709 wiphy->n_iface_combinations = 1;
710#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800711
Jeff Johnson295189b2012-06-20 16:38:30 -0700712 /* Before registering we need to update the ht capabilitied based
713 * on ini values*/
714 if( !pCfg->ShortGI20MhzEnable )
715 {
716 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
717 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
718 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
719 }
720
721 if( !pCfg->ShortGI40MhzEnable )
722 {
723 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
724 }
725
726 if( !pCfg->nChannelBondingMode5GHz )
727 {
728 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
729 }
730
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530731 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
732 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
733
734 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
735 {
736
737 if (NULL == wiphy->bands[i])
738 {
739 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[i] is NULL, i = %d",
740 __func__, i);
741 continue;
742 }
743
744 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
745 {
746 struct ieee80211_supported_band *band = wiphy->bands[i];
747
748 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == pCfg->nBandCapability) // 5G only
749 {
750 // Enable social channels for P2P
751 if (WLAN_HDD_IS_SOCIAL_CHANNEL(band->channels[j].center_freq))
752 band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED;
753 else
754 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
755 continue;
756 }
757 else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == pCfg->nBandCapability) // 2G only
758 {
759 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
760 continue;
761 }
762 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700763 }
764 /*Initialise the supported cipher suite details*/
765 wiphy->cipher_suites = hdd_cipher_suites;
766 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
767
768 /*signal strength in mBm (100*dBm) */
769 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
770
771#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -0700772 wiphy->max_remain_on_channel_duration = 1000;
773#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700774
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530775 EXIT();
776 return 0;
777}
778
779/* In this function we are registering wiphy. */
780int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
781{
782 ENTER();
783 /* Register our wiphy dev with cfg80211 */
Jeff Johnson295189b2012-06-20 16:38:30 -0700784 if (0 > wiphy_register(wiphy))
785 {
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530786 /* print error */
Jeff Johnson295189b2012-06-20 16:38:30 -0700787 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
788 return -EIO;
789 }
790
791 EXIT();
792 return 0;
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530793}
Jeff Johnson295189b2012-06-20 16:38:30 -0700794
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530795/* In this function we are updating channel list when,
796 regulatory domain is FCC and country code is US.
797 Here In FCC standard 5GHz UNII-1 Bands are indoor only.
798 As per FCC smart phone is not a indoor device.
799 GO should not opeate on indoor channels */
800void wlan_hdd_cfg80211_update_reg_info(struct wiphy *wiphy)
801{
802 int j;
803 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
804 tANI_U8 defaultCountryCode[3] = SME_INVALID_COUNTRY_CODE;
805 //Default counrtycode from NV at the time of wiphy initialization.
806 if (eHAL_STATUS_SUCCESS != sme_GetDefaultCountryCodeFrmNv(pHddCtx->hHal,
807 &defaultCountryCode[0]))
808 {
809 hddLog(LOGE, FL("%s Failed to get default country code from NV"));
810 }
811 if ((defaultCountryCode[0]== 'U') && (defaultCountryCode[1]=='S'))
812 {
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530813 if (NULL == wiphy->bands[IEEE80211_BAND_5GHZ])
814 {
815 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[IEEE80211_BAND_5GHZ] is NULL",__func__ );
816 return;
817 }
818 for (j = 0; j < wiphy->bands[IEEE80211_BAND_5GHZ]->n_channels; j++)
819 {
820 struct ieee80211_supported_band *band = wiphy->bands[IEEE80211_BAND_5GHZ];
821 // Mark UNII -1 band channel as passive
822 if (WLAN_HDD_CHANNEL_IN_UNII_1_BAND(band->channels[j].center_freq))
823 band->channels[j].flags |= IEEE80211_CHAN_PASSIVE_SCAN;
824 }
825 }
826}
827
Jeff Johnson295189b2012-06-20 16:38:30 -0700828/* In this function we will do all post VOS start initialization.
829 In this function we will register for all frame in which supplicant
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530830 is interested.
Jeff Johnson295189b2012-06-20 16:38:30 -0700831*/
832void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
833{
Jeff Johnson295189b2012-06-20 16:38:30 -0700834 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
835 /* Register for all P2P action, public action etc frames */
836 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
837
Jeff Johnsone7245742012-09-05 17:12:55 -0700838 ENTER();
839
Jeff Johnson295189b2012-06-20 16:38:30 -0700840 /* Right now we are registering these frame when driver is getting
841 initialized. Once we will move to 2.6.37 kernel, in which we have
842 frame register ops, we will move this code as a part of that */
843 /* GAS Initial Request */
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530844 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
Jeff Johnson295189b2012-06-20 16:38:30 -0700845 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
846
847 /* GAS Initial Response */
848 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
849 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530850
Jeff Johnson295189b2012-06-20 16:38:30 -0700851 /* GAS Comeback Request */
852 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
853 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
854
855 /* GAS Comeback Response */
856 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
857 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
858
859 /* P2P Public Action */
860 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530861 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
Jeff Johnson295189b2012-06-20 16:38:30 -0700862 P2P_PUBLIC_ACTION_FRAME_SIZE );
863
864 /* P2P Action */
865 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
866 (v_U8_t*)P2P_ACTION_FRAME,
867 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -0700868
Gopichand Nakkalae3d56e72013-04-21 23:33:32 +0530869 /* WNM BSS Transition Request frame */
870 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
871 (v_U8_t*)WNM_BSS_ACTION_FRAME,
872 WNM_BSS_ACTION_FRAME_SIZE );
873
Chet Lanctot186b5732013-03-18 10:26:30 -0700874#ifdef WLAN_FEATURE_11W
875 /* SA Query Response Action Frame */
876 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
877 (v_U8_t*)SA_QUERY_FRAME_RSP,
878 SA_QUERY_FRAME_RSP_SIZE );
879#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -0700880}
881
882void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
883{
Jeff Johnson295189b2012-06-20 16:38:30 -0700884 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
885 /* Register for all P2P action, public action etc frames */
886 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
887
Jeff Johnsone7245742012-09-05 17:12:55 -0700888 ENTER();
889
Jeff Johnson295189b2012-06-20 16:38:30 -0700890 /* Right now we are registering these frame when driver is getting
891 initialized. Once we will move to 2.6.37 kernel, in which we have
892 frame register ops, we will move this code as a part of that */
893 /* GAS Initial Request */
894
895 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
896 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
897
898 /* GAS Initial Response */
899 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
900 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530901
Jeff Johnson295189b2012-06-20 16:38:30 -0700902 /* GAS Comeback Request */
903 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
904 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
905
906 /* GAS Comeback Response */
907 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
908 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
909
910 /* P2P Public Action */
911 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530912 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
Jeff Johnson295189b2012-06-20 16:38:30 -0700913 P2P_PUBLIC_ACTION_FRAME_SIZE );
914
915 /* P2P Action */
916 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
917 (v_U8_t*)P2P_ACTION_FRAME,
918 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -0700919
920#ifdef WLAN_FEATURE_11W
921 /* SA Query Response Action Frame */
922 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
923 (v_U8_t*)SA_QUERY_FRAME_RSP,
924 SA_QUERY_FRAME_RSP_SIZE );
925#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -0700926}
927
928#ifdef FEATURE_WLAN_WAPI
929void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
930 const u8 *mac_addr, u8 *key , int key_Len)
931{
932 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
933 tCsrRoamSetKey setKey;
934 v_BOOL_t isConnected = TRUE;
935 int status = 0;
936 v_U32_t roamId= 0xFF;
937 tANI_U8 *pKeyPtr = NULL;
938 int n = 0;
939
940 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
941 __func__,pAdapter->device_mode);
942
Gopichand Nakkalae7480202013-02-11 15:24:22 +0530943 vos_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Jeff Johnson295189b2012-06-20 16:38:30 -0700944 setKey.keyId = key_index; // Store Key ID
945 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
946 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
947 setKey.paeRole = 0 ; // the PAE role
948 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
949 {
950 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
951 }
952 else
953 {
954 isConnected = hdd_connIsConnected(pHddStaCtx);
955 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
956 }
957 setKey.keyLength = key_Len;
958 pKeyPtr = setKey.Key;
959 memcpy( pKeyPtr, key, key_Len);
960
961 hddLog(VOS_TRACE_LEVEL_INFO,"\n%s: WAPI KEY LENGTH:0x%04x",
962 __func__, key_Len);
963 for (n = 0 ; n < key_Len; n++)
964 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
965 __func__,n,setKey.Key[n]);
966
967 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
968 if ( isConnected )
969 {
970 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
971 pAdapter->sessionId, &setKey, &roamId );
972 }
973 if ( status != 0 )
974 {
975 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
976 "[%4d] sme_RoamSetKey returned ERROR status= %d",
977 __LINE__, status );
978 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
979 }
980}
981#endif /* FEATURE_WLAN_WAPI*/
982
983#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530984int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -0700985 beacon_data_t **ppBeacon,
986 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700987#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530988int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700989 beacon_data_t **ppBeacon,
990 struct cfg80211_beacon_data *params,
991 int dtim_period)
992#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530993{
Jeff Johnson295189b2012-06-20 16:38:30 -0700994 int size;
995 beacon_data_t *beacon = NULL;
996 beacon_data_t *old = NULL;
997 int head_len,tail_len;
998
Jeff Johnsone7245742012-09-05 17:12:55 -0700999 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07001000 if (params->head && !params->head_len)
1001 return -EINVAL;
1002
1003 old = pAdapter->sessionCtx.ap.beacon;
1004
1005 if (!params->head && !old)
1006 return -EINVAL;
1007
1008 if (params->tail && !params->tail_len)
1009 return -EINVAL;
1010
1011#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
1012 /* Kernel 3.0 is not updating dtim_period for set beacon */
1013 if (!params->dtim_period)
1014 return -EINVAL;
1015#endif
1016
1017 if(params->head)
1018 head_len = params->head_len;
1019 else
1020 head_len = old->head_len;
1021
1022 if(params->tail || !old)
1023 tail_len = params->tail_len;
1024 else
1025 tail_len = old->tail_len;
1026
1027 size = sizeof(beacon_data_t) + head_len + tail_len;
1028
1029 beacon = kzalloc(size, GFP_KERNEL);
1030
1031 if( beacon == NULL )
1032 return -ENOMEM;
1033
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001034#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001035 if(params->dtim_period || !old )
1036 beacon->dtim_period = params->dtim_period;
1037 else
1038 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001039#else
1040 if(dtim_period || !old )
1041 beacon->dtim_period = dtim_period;
1042 else
1043 beacon->dtim_period = old->dtim_period;
1044#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301045
Jeff Johnson295189b2012-06-20 16:38:30 -07001046 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
1047 beacon->tail = beacon->head + head_len;
1048 beacon->head_len = head_len;
1049 beacon->tail_len = tail_len;
1050
1051 if(params->head) {
1052 memcpy (beacon->head,params->head,beacon->head_len);
1053 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301054 else {
Jeff Johnson295189b2012-06-20 16:38:30 -07001055 if(old)
1056 memcpy (beacon->head,old->head,beacon->head_len);
1057 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301058
Jeff Johnson295189b2012-06-20 16:38:30 -07001059 if(params->tail) {
1060 memcpy (beacon->tail,params->tail,beacon->tail_len);
1061 }
1062 else {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301063 if(old)
Jeff Johnson295189b2012-06-20 16:38:30 -07001064 memcpy (beacon->tail,old->tail,beacon->tail_len);
1065 }
1066
1067 *ppBeacon = beacon;
1068
1069 kfree(old);
1070
1071 return 0;
1072
1073}
Jeff Johnson295189b2012-06-20 16:38:30 -07001074
1075v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
1076{
1077 int left = length;
1078 v_U8_t *ptr = pIes;
1079 v_U8_t elem_id,elem_len;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301080
Jeff Johnson295189b2012-06-20 16:38:30 -07001081 while(left >= 2)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301082 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001083 elem_id = ptr[0];
1084 elem_len = ptr[1];
1085 left -= 2;
1086 if(elem_len > left)
1087 {
1088 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001089 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -07001090 eid,elem_len,left);
1091 return NULL;
1092 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301093 if (elem_id == eid)
Jeff Johnson295189b2012-06-20 16:38:30 -07001094 {
1095 return ptr;
1096 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301097
Jeff Johnson295189b2012-06-20 16:38:30 -07001098 left -= elem_len;
1099 ptr += (elem_len + 2);
1100 }
1101 return NULL;
1102}
1103
Jeff Johnson295189b2012-06-20 16:38:30 -07001104/* Check if rate is 11g rate or not */
1105static int wlan_hdd_rate_is_11g(u8 rate)
1106{
Sanjay Devnani28322e22013-06-21 16:13:40 -07001107 static const u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 108}; /* actual rate * 2 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001108 u8 i;
1109 for (i = 0; i < 8; i++)
1110 {
1111 if(rate == gRateArray[i])
1112 return TRUE;
1113 }
1114 return FALSE;
1115}
1116
1117/* Check for 11g rate and set proper 11g only mode */
1118static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
1119 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
1120{
1121 u8 i, num_rates = pIe[0];
1122
1123 pIe += 1;
1124 for ( i = 0; i < num_rates; i++)
1125 {
1126 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
1127 {
1128 /* If rate set have 11g rate than change the mode to 11G */
1129 *pSapHw_mode = eSAP_DOT11_MODE_11g;
1130 if (pIe[i] & BASIC_RATE_MASK)
1131 {
1132 /* If we have 11g rate as basic rate, it means mode
1133 is 11g only mode.
1134 */
1135 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
1136 *pCheckRatesfor11g = FALSE;
1137 }
1138 }
1139 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
1140 {
1141 *require_ht = TRUE;
1142 }
1143 }
1144 return;
1145}
1146
1147static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
1148{
1149 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1150 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1151 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1152 u8 checkRatesfor11g = TRUE;
1153 u8 require_ht = FALSE;
1154 u8 *pIe=NULL;
1155
1156 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
1157
1158 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
1159 pBeacon->head_len, WLAN_EID_SUPP_RATES);
1160 if (pIe != NULL)
1161 {
1162 pIe += 1;
1163 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1164 &pConfig->SapHw_mode);
1165 }
1166
1167 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1168 WLAN_EID_EXT_SUPP_RATES);
1169 if (pIe != NULL)
1170 {
1171
1172 pIe += 1;
1173 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1174 &pConfig->SapHw_mode);
1175 }
1176
1177 if( pConfig->channel > 14 )
1178 {
1179 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
1180 }
1181
1182 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1183 WLAN_EID_HT_CAPABILITY);
1184
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301185 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001186 {
1187 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
1188 if(require_ht)
1189 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
1190 }
1191}
1192
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301193static int wlan_hdd_add_ie(hdd_adapter_t* pHostapdAdapter, v_U8_t *genie,
1194 v_U8_t *total_ielen, v_U8_t *oui, v_U8_t oui_size)
1195{
Arif Hussaine7f3ea52013-09-12 21:56:36 -07001196 v_U16_t ielen = 0;
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301197 v_U8_t *pIe = NULL;
1198 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1199
1200 pIe = wlan_hdd_get_vendor_oui_ie_ptr(oui, oui_size,
1201 pBeacon->tail, pBeacon->tail_len);
1202
1203 if (pIe)
1204 {
1205 ielen = pIe[1] + 2;
1206 if ((*total_ielen + ielen) <= MAX_GENIE_LEN)
1207 {
1208 vos_mem_copy(&genie[*total_ielen], pIe, ielen);
1209 }
1210 else
1211 {
1212 hddLog( VOS_TRACE_LEVEL_ERROR, "**Ie Length is too big***");
1213 return -EINVAL;
1214 }
1215 *total_ielen += ielen;
1216 }
1217 return 0;
1218}
1219
Arif Hussaine7f3ea52013-09-12 21:56:36 -07001220static void wlan_hdd_add_hostapd_conf_vsie(hdd_adapter_t* pHostapdAdapter,
1221 v_U8_t *genie, v_U8_t *total_ielen)
1222{
1223 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1224 int left = pBeacon->tail_len;
1225 v_U8_t *ptr = pBeacon->tail;
1226 v_U8_t elem_id, elem_len;
1227 v_U16_t ielen = 0;
1228
1229 if ( NULL == ptr || 0 == left )
1230 return;
1231
1232 while (left >= 2)
1233 {
1234 elem_id = ptr[0];
1235 elem_len = ptr[1];
1236 left -= 2;
1237 if (elem_len > left)
1238 {
1239 hddLog( VOS_TRACE_LEVEL_ERROR,
1240 "****Invalid IEs eid = %d elem_len=%d left=%d*****",
1241 elem_id, elem_len, left);
1242 return;
1243 }
1244 if (IE_EID_VENDOR == elem_id)
1245 {
1246 /* skipping the VSIE's which we don't want to include or
1247 * it will be included by existing code
1248 */
1249 if ((memcmp( &ptr[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) != 0 ) &&
1250#ifdef WLAN_FEATURE_WFD
1251 (memcmp( &ptr[2], WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE) != 0) &&
1252#endif
1253 (memcmp( &ptr[2], WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) &&
1254 (memcmp( &ptr[2], BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) &&
1255 (memcmp( &ptr[2], "\x00\x50\xf2\x02", WPA_OUI_TYPE_SIZE) != 0) &&
1256 (memcmp( &ptr[2], WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) &&
1257 (memcmp( &ptr[2], P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE) != 0))
1258 {
1259 ielen = ptr[1] + 2;
1260 if ((*total_ielen + ielen) <= MAX_GENIE_LEN)
1261 {
1262 vos_mem_copy(&genie[*total_ielen], ptr, ielen);
1263 *total_ielen += ielen;
1264 }
1265 else
1266 {
1267 hddLog( VOS_TRACE_LEVEL_ERROR,
1268 "IE Length is too big "
1269 "IEs eid=%d elem_len=%d total_ie_lent=%d",
1270 elem_id, elem_len, *total_ielen);
1271 }
1272 }
1273 }
1274
1275 left -= elem_len;
1276 ptr += (elem_len + 2);
1277 }
1278 return;
1279}
1280
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001281#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001282static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1283 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001284#else
1285static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1286 struct cfg80211_beacon_data *params)
1287#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001288{
1289 v_U8_t *genie;
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301290 v_U8_t total_ielen = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001291 v_U8_t addIE[1] = {0};
Jeff Johnsone7245742012-09-05 17:12:55 -07001292 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001293
1294 genie = vos_mem_malloc(MAX_GENIE_LEN);
1295
1296 if(genie == NULL) {
1297
1298 return -ENOMEM;
1299 }
1300
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301301 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1302 &total_ielen, WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001303 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301304 ret = -EINVAL;
1305 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001306 }
1307
1308#ifdef WLAN_FEATURE_WFD
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301309 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1310 &total_ielen, WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE))
1311 {
1312 ret = -EINVAL;
1313 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001314 }
1315#endif
1316
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301317 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1318 &total_ielen, P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001319 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301320 ret = -EINVAL;
1321 goto done;
1322 }
1323
1324 if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode)
1325 {
Arif Hussaine7f3ea52013-09-12 21:56:36 -07001326 wlan_hdd_add_hostapd_conf_vsie(pHostapdAdapter, genie, &total_ielen);
Jeff Johnson295189b2012-06-20 16:38:30 -07001327 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001328
1329 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1330 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1331 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1332 {
1333 hddLog(LOGE,
1334 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001335 ret = -EINVAL;
1336 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001337 }
1338
1339 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1340 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1341 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1342 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1343 ==eHAL_STATUS_FAILURE)
1344 {
1345 hddLog(LOGE,
1346 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001347 ret = -EINVAL;
1348 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001349 }
1350
1351 // Added for ProResp IE
1352 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1353 {
1354 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1355 u8 probe_rsp_ie_len[3] = {0};
1356 u8 counter = 0;
1357 /* Check Probe Resp Length if it is greater then 255 then Store
1358 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1359 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1360 Store More then 255 bytes into One Variable.
1361 */
1362 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1363 {
1364 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1365 {
1366 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1367 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1368 }
1369 else
1370 {
1371 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1372 rem_probe_resp_ie_len = 0;
1373 }
1374 }
1375
1376 rem_probe_resp_ie_len = 0;
1377
1378 if (probe_rsp_ie_len[0] > 0)
1379 {
1380 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1381 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1382 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1383 probe_rsp_ie_len[0], NULL,
1384 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1385 {
1386 hddLog(LOGE,
1387 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001388 ret = -EINVAL;
1389 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001390 }
1391 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1392 }
1393
1394 if (probe_rsp_ie_len[1] > 0)
1395 {
1396 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1397 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1398 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1399 probe_rsp_ie_len[1], NULL,
1400 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1401 {
1402 hddLog(LOGE,
1403 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001404 ret = -EINVAL;
1405 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001406 }
1407 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1408 }
1409
1410 if (probe_rsp_ie_len[2] > 0)
1411 {
1412 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1413 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1414 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1415 probe_rsp_ie_len[2], NULL,
1416 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1417 {
1418 hddLog(LOGE,
1419 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001420 ret = -EINVAL;
1421 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001422 }
1423 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1424 }
1425
1426 if (probe_rsp_ie_len[1] == 0 )
1427 {
1428 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1429 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1430 eANI_BOOLEAN_FALSE) )
1431 {
1432 hddLog(LOGE,
1433 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1434 }
1435 }
1436
1437 if (probe_rsp_ie_len[2] == 0 )
1438 {
1439 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1440 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1441 eANI_BOOLEAN_FALSE) )
1442 {
1443 hddLog(LOGE,
1444 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1445 }
1446 }
1447
1448 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1449 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1450 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1451 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1452 == eHAL_STATUS_FAILURE)
1453 {
1454 hddLog(LOGE,
1455 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001456 ret = -EINVAL;
1457 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001458 }
1459 }
1460 else
1461 {
1462 // Reset WNI_CFG_PROBE_RSP Flags
1463 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1464
1465 hddLog(VOS_TRACE_LEVEL_INFO,
1466 "%s: No Probe Response IE received in set beacon",
1467 __func__);
1468 }
1469
1470 // Added for AssocResp IE
1471 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1472 {
1473 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1474 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1475 params->assocresp_ies_len, NULL,
1476 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1477 {
1478 hddLog(LOGE,
1479 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001480 ret = -EINVAL;
1481 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001482 }
1483
1484 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1485 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1486 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1487 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1488 == eHAL_STATUS_FAILURE)
1489 {
1490 hddLog(LOGE,
1491 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001492 ret = -EINVAL;
1493 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001494 }
1495 }
1496 else
1497 {
1498 hddLog(VOS_TRACE_LEVEL_INFO,
1499 "%s: No Assoc Response IE received in set beacon",
1500 __func__);
1501
1502 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1503 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1504 eANI_BOOLEAN_FALSE) )
1505 {
1506 hddLog(LOGE,
1507 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1508 }
1509 }
1510
Jeff Johnsone7245742012-09-05 17:12:55 -07001511done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001512 vos_mem_free(genie);
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301513 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07001514}
Jeff Johnson295189b2012-06-20 16:38:30 -07001515
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301516/*
Jeff Johnson295189b2012-06-20 16:38:30 -07001517 * FUNCTION: wlan_hdd_validate_operation_channel
1518 * called by wlan_hdd_cfg80211_start_bss() and
1519 * wlan_hdd_cfg80211_set_channel()
1520 * This function validates whether given channel is part of valid
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301521 * channel list.
1522 */
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001523VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001524{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301525
Jeff Johnson295189b2012-06-20 16:38:30 -07001526 v_U32_t num_ch = 0;
1527 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1528 u32 indx = 0;
1529 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301530 v_U8_t fValidChannel = FALSE, count = 0;
1531 hdd_config_t *hdd_pConfig_ini= (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301532
Jeff Johnson295189b2012-06-20 16:38:30 -07001533 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1534
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301535 if ( hdd_pConfig_ini->sapAllowAllChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001536 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301537 /* Validate the channel */
1538 for (count = RF_CHAN_1 ; count <= RF_CHAN_165 ; count++)
Jeff Johnson295189b2012-06-20 16:38:30 -07001539 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301540 if ( channel == rfChannels[count].channelNum )
1541 {
1542 fValidChannel = TRUE;
1543 break;
1544 }
1545 }
1546 if (fValidChannel != TRUE)
1547 {
1548 hddLog(VOS_TRACE_LEVEL_ERROR,
1549 "%s: Invalid Channel [%d]", __func__, channel);
1550 return VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001551 }
1552 }
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301553 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001554 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301555 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1556 valid_ch, &num_ch))
1557 {
1558 hddLog(VOS_TRACE_LEVEL_ERROR,
1559 "%s: failed to get valid channel list", __func__);
1560 return VOS_STATUS_E_FAILURE;
1561 }
1562 for (indx = 0; indx < num_ch; indx++)
1563 {
1564 if (channel == valid_ch[indx])
1565 {
1566 break;
1567 }
1568 }
1569
1570 if (indx >= num_ch)
1571 {
1572 hddLog(VOS_TRACE_LEVEL_ERROR,
1573 "%s: Invalid Channel [%d]", __func__, channel);
1574 return VOS_STATUS_E_FAILURE;
1575 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001576 }
1577 return VOS_STATUS_SUCCESS;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301578
Jeff Johnson295189b2012-06-20 16:38:30 -07001579}
1580
Viral Modi3a32cc52013-02-08 11:14:52 -08001581/**
1582 * FUNCTION: wlan_hdd_cfg80211_set_channel
1583 * This function is used to set the channel number
1584 */
1585static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
1586 struct ieee80211_channel *chan,
1587 enum nl80211_channel_type channel_type
1588 )
1589{
1590 v_U32_t num_ch = 0;
Jeff Johnson4416a782013-03-25 14:17:50 -07001591 int channel = 0;
Viral Modi3a32cc52013-02-08 11:14:52 -08001592 hdd_adapter_t *pAdapter = NULL;
1593 int freq = chan->center_freq; /* freq is in MHZ */
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301594 hdd_context_t *pHddCtx;
1595 int status;
Viral Modi3a32cc52013-02-08 11:14:52 -08001596
1597 ENTER();
1598
1599 if( NULL == dev )
1600 {
1601 hddLog(VOS_TRACE_LEVEL_ERROR,
1602 "%s: Called with dev = NULL.\n", __func__);
1603 return -ENODEV;
1604 }
1605 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1606
1607 hddLog(VOS_TRACE_LEVEL_INFO,
1608 "%s: device_mode = %d freq = %d \n",__func__,
1609 pAdapter->device_mode, chan->center_freq);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301610
1611 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1612 status = wlan_hdd_validate_context(pHddCtx);
1613
1614 if (0 != status)
Viral Modi3a32cc52013-02-08 11:14:52 -08001615 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301616 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1617 "%s: HDD context is not valid", __func__);
1618 return status;
Viral Modi3a32cc52013-02-08 11:14:52 -08001619 }
1620
1621 /*
1622 * Do freq to chan conversion
1623 * TODO: for 11a
1624 */
1625
1626 channel = ieee80211_frequency_to_channel(freq);
1627
1628 /* Check freq range */
1629 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
1630 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
1631 {
1632 hddLog(VOS_TRACE_LEVEL_ERROR,
1633 "%s: Channel [%d] is outside valid range from %d to %d\n",
1634 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
1635 WNI_CFG_CURRENT_CHANNEL_STAMAX);
1636 return -EINVAL;
1637 }
1638
1639 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1640
Gopichand Nakkala6ab19562013-03-07 13:59:42 +05301641 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode) &&
1642 (WLAN_HDD_P2P_GO != pAdapter->device_mode))
Viral Modi3a32cc52013-02-08 11:14:52 -08001643 {
1644 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
1645 {
1646 hddLog(VOS_TRACE_LEVEL_ERROR,
1647 "%s: Invalid Channel [%d] \n", __func__, channel);
1648 return -EINVAL;
1649 }
1650 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1651 "%s: set channel to [%d] for device mode =%d",
1652 __func__, channel,pAdapter->device_mode);
1653 }
1654 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Viral Modi3a32cc52013-02-08 11:14:52 -08001655 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Viral Modi3a32cc52013-02-08 11:14:52 -08001656 )
1657 {
1658 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
1659 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
1660 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1661
1662 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
1663 {
1664 /* Link is up then return cant set channel*/
1665 hddLog( VOS_TRACE_LEVEL_ERROR,
1666 "%s: IBSS Associated, can't set the channel\n", __func__);
1667 return -EINVAL;
1668 }
1669
1670 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
1671 pHddStaCtx->conn_info.operationChannel = channel;
1672 pRoamProfile->ChannelInfo.ChannelList =
1673 &pHddStaCtx->conn_info.operationChannel;
1674 }
1675 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Viral Modi3a32cc52013-02-08 11:14:52 -08001676 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Viral Modi3a32cc52013-02-08 11:14:52 -08001677 )
1678 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301679 if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
1680 {
1681 if(VOS_STATUS_SUCCESS !=
1682 wlan_hdd_validate_operation_channel(pAdapter,channel))
1683 {
1684 hddLog(VOS_TRACE_LEVEL_ERROR,
1685 "%s: Invalid Channel [%d] \n", __func__, channel);
1686 return -EINVAL;
1687 }
1688 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1689 }
1690 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
Viral Modi3a32cc52013-02-08 11:14:52 -08001691 {
1692 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
1693
1694 /* If auto channel selection is configured as enable/ 1 then ignore
1695 channel set by supplicant
1696 */
1697 if ( cfg_param->apAutoChannelSelection )
1698 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301699 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel =
1700 AUTO_CHANNEL_SELECT;
Viral Modi3a32cc52013-02-08 11:14:52 -08001701 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1702 "%s: set channel to auto channel (0) for device mode =%d",
1703 __func__, pAdapter->device_mode);
1704 }
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301705 else
1706 {
1707 if(VOS_STATUS_SUCCESS !=
1708 wlan_hdd_validate_operation_channel(pAdapter,channel))
1709 {
1710 hddLog(VOS_TRACE_LEVEL_ERROR,
1711 "%s: Invalid Channel [%d] \n", __func__, channel);
1712 return -EINVAL;
1713 }
1714 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1715 }
Viral Modi3a32cc52013-02-08 11:14:52 -08001716 }
1717 }
1718 else
1719 {
1720 hddLog(VOS_TRACE_LEVEL_FATAL,
1721 "%s: Invalid device mode failed to set valid channel", __func__);
1722 return -EINVAL;
1723 }
1724 EXIT();
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301725 return status;
Viral Modi3a32cc52013-02-08 11:14:52 -08001726}
1727
Jeff Johnson295189b2012-06-20 16:38:30 -07001728#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1729static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1730 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001731#else
1732static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1733 struct cfg80211_beacon_data *params,
1734 const u8 *ssid, size_t ssid_len,
1735 enum nl80211_hidden_ssid hidden_ssid)
1736#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001737{
1738 tsap_Config_t *pConfig;
1739 beacon_data_t *pBeacon = NULL;
1740 struct ieee80211_mgmt *pMgmt_frame;
1741 v_U8_t *pIe=NULL;
1742 v_U16_t capab_info;
1743 eCsrAuthType RSNAuthType;
1744 eCsrEncryptionType RSNEncryptType;
1745 eCsrEncryptionType mcRSNEncryptType;
1746 int status = VOS_STATUS_SUCCESS;
1747 tpWLAN_SAPEventCB pSapEventCallback;
1748 hdd_hostapd_state_t *pHostapdState;
1749 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1750 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301751 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001752 struct qc_mac_acl_entry *acl_entry = NULL;
1753 v_SINT_t i;
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001754 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001755
1756 ENTER();
1757
1758 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1759
1760 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1761
1762 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1763
1764 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1765
1766 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1767
1768 //channel is already set in the set_channel Call back
1769 //pConfig->channel = pCommitConfig->channel;
1770
1771 /*Protection parameter to enable or disable*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301772 pConfig->protEnabled =
Jeff Johnson295189b2012-06-20 16:38:30 -07001773 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1774
1775 pConfig->dtim_period = pBeacon->dtim_period;
1776
1777 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1778 pConfig->dtim_period);
1779
1780
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001781 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001782 {
1783 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001784 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001785 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001786 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001787 tANI_BOOLEAN restartNeeded;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001788 pConfig->ieee80211d = 1;
1789 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1790 sme_setRegInfo(hHal, pConfig->countryCode);
1791 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
Jeff Johnson295189b2012-06-20 16:38:30 -07001792 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001793 else
1794 {
1795 pConfig->ieee80211d = 0;
1796 }
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301797 /*
1798 * If auto channel is configured i.e. channel is 0,
1799 * so skip channel validation.
1800 */
1801 if( AUTO_CHANNEL_SELECT != pConfig->channel )
1802 {
1803 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1804 {
1805 hddLog(VOS_TRACE_LEVEL_ERROR,
1806 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1807 return -EINVAL;
1808 }
1809 }
1810 else
1811 {
1812 if(1 != pHddCtx->is_dynamic_channel_range_set)
1813 {
1814 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
1815 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
1816 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
1817 }
1818 pHddCtx->is_dynamic_channel_range_set = 0;
1819 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001820 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001821 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001822 {
1823 pConfig->ieee80211d = 0;
1824 }
1825 pConfig->authType = eSAP_AUTO_SWITCH;
1826
1827 capab_info = pMgmt_frame->u.beacon.capab_info;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301828
1829 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
Jeff Johnson295189b2012-06-20 16:38:30 -07001830 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1831
1832 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1833
1834 /*Set wps station to configured*/
1835 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1836
1837 if(pIe)
1838 {
1839 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1840 {
1841 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1842 return -EINVAL;
1843 }
1844 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1845 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001846 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001847 /* Check 15 bit of WPS IE as it contain information for wps state
1848 * WPS state
1849 */
1850 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1851 {
1852 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1853 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1854 {
1855 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1856 }
1857 }
1858 }
1859 else
1860 {
1861 pConfig->wps_state = SAP_WPS_DISABLED;
1862 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301863 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
Jeff Johnson295189b2012-06-20 16:38:30 -07001864
1865 pConfig->RSNWPAReqIELength = 0;
1866 pConfig->pRSNWPAReqIE = NULL;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301867 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001868 WLAN_EID_RSN);
1869 if(pIe && pIe[1])
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301870 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001871 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1872 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1873 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301874 /* The actual processing may eventually be more extensive than
1875 * this. Right now, just consume any PMKIDs that are sent in
Jeff Johnson295189b2012-06-20 16:38:30 -07001876 * by the app.
1877 * */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301878 status = hdd_softap_unpackIE(
Jeff Johnson295189b2012-06-20 16:38:30 -07001879 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1880 &RSNEncryptType,
1881 &mcRSNEncryptType,
1882 &RSNAuthType,
1883 pConfig->pRSNWPAReqIE[1]+2,
1884 pConfig->pRSNWPAReqIE );
1885
1886 if( VOS_STATUS_SUCCESS == status )
1887 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301888 /* Now copy over all the security attributes you have
1889 * parsed out
Jeff Johnson295189b2012-06-20 16:38:30 -07001890 * */
1891 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1892 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1893 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1894 = RSNEncryptType;
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05301895 hddLog( LOG1, FL("CSR AuthType = %d, "
Jeff Johnson295189b2012-06-20 16:38:30 -07001896 "EncryptionType = %d mcEncryptionType = %d\n"),
1897 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1898 }
1899 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301900
Jeff Johnson295189b2012-06-20 16:38:30 -07001901 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1902 pBeacon->tail, pBeacon->tail_len);
1903
1904 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1905 {
1906 if (pConfig->pRSNWPAReqIE)
1907 {
1908 /*Mixed mode WPA/WPA2*/
1909 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1910 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1911 }
1912 else
1913 {
1914 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1915 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1916 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301917 status = hdd_softap_unpackIE(
Jeff Johnson295189b2012-06-20 16:38:30 -07001918 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1919 &RSNEncryptType,
1920 &mcRSNEncryptType,
1921 &RSNAuthType,
1922 pConfig->pRSNWPAReqIE[1]+2,
1923 pConfig->pRSNWPAReqIE );
1924
1925 if( VOS_STATUS_SUCCESS == status )
1926 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301927 /* Now copy over all the security attributes you have
1928 * parsed out
Jeff Johnson295189b2012-06-20 16:38:30 -07001929 * */
1930 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1931 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1932 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1933 = RSNEncryptType;
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05301934 hddLog( LOG1, FL("CSR AuthType = %d, "
Jeff Johnson295189b2012-06-20 16:38:30 -07001935 "EncryptionType = %d mcEncryptionType = %d\n"),
1936 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1937 }
1938 }
1939 }
1940
Jeff Johnson4416a782013-03-25 14:17:50 -07001941 if (pConfig->RSNWPAReqIELength > sizeof wpaRsnIEdata) {
1942 hddLog( VOS_TRACE_LEVEL_ERROR, "**RSNWPAReqIELength is too large***");
1943 return -EINVAL;
1944 }
1945
Jeff Johnson295189b2012-06-20 16:38:30 -07001946 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1947
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001948#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001949 if (params->ssid != NULL)
1950 {
1951 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1952 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1953 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1954 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1955 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001956#else
1957 if (ssid != NULL)
1958 {
1959 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1960 pConfig->SSIDinfo.ssid.length = ssid_len;
1961 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1962 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1963 }
1964#endif
1965
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301966 vos_mem_copy(pConfig->self_macaddr.bytes,
Jeff Johnson295189b2012-06-20 16:38:30 -07001967 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301968
Jeff Johnson295189b2012-06-20 16:38:30 -07001969 /* default value */
1970 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1971 pConfig->num_accept_mac = 0;
1972 pConfig->num_deny_mac = 0;
1973
1974 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1975 pBeacon->tail, pBeacon->tail_len);
1976
1977 /* pIe for black list is following form:
1978 type : 1 byte
1979 length : 1 byte
1980 OUI : 4 bytes
1981 acl type : 1 byte
1982 no of mac addr in black list: 1 byte
1983 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301984 */
1985 if ((pIe != NULL) && (pIe[1] != 0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001986 {
1987 pConfig->SapMacaddr_acl = pIe[6];
1988 pConfig->num_deny_mac = pIe[7];
1989 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1990 pIe[6], pIe[7]);
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05301991 if (pConfig->num_deny_mac > MAX_ACL_MAC_ADDRESS)
1992 pConfig->num_deny_mac = MAX_ACL_MAC_ADDRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07001993 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1994 for (i = 0; i < pConfig->num_deny_mac; i++)
1995 {
1996 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1997 acl_entry++;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301998 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001999 }
2000 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
2001 pBeacon->tail, pBeacon->tail_len);
2002
2003 /* pIe for white list is following form:
2004 type : 1 byte
2005 length : 1 byte
2006 OUI : 4 bytes
2007 acl type : 1 byte
2008 no of mac addr in white list: 1 byte
2009 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302010 */
2011 if ((pIe != NULL) && (pIe[1] != 0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002012 {
2013 pConfig->SapMacaddr_acl = pIe[6];
2014 pConfig->num_accept_mac = pIe[7];
2015 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
2016 pIe[6], pIe[7]);
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05302017 if (pConfig->num_accept_mac > MAX_ACL_MAC_ADDRESS)
2018 pConfig->num_accept_mac = MAX_ACL_MAC_ADDRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07002019 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
2020 for (i = 0; i < pConfig->num_accept_mac; i++)
2021 {
2022 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
2023 acl_entry++;
2024 }
2025 }
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05302026
Jeff Johnson295189b2012-06-20 16:38:30 -07002027 wlan_hdd_set_sapHwmode(pHostapdAdapter);
2028
Jeff Johnsone7245742012-09-05 17:12:55 -07002029#ifdef WLAN_FEATURE_11AC
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08002030 /* Overwrite the hostapd setting for HW mode only for 11ac.
2031 * This is valid only if mode is set to 11n in hostapd and either AUTO or 11ac in .ini .
2032 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode) */
2033 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
2034 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302035 (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08002036 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
2037 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07002038 {
2039 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
Ravi Joshi83bfaa12013-05-28 22:12:08 -07002040
2041 /* Disable VHT support in 2.4 GHz band */
2042 if (pConfig->channel <= 14 &&
2043 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->enableVhtFor24GHzBand == FALSE)
2044 {
2045 pConfig->SapHw_mode = eSAP_DOT11_MODE_11n;
2046 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002047 }
2048#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302049
Ravi Joshiaeb7d9e2013-05-02 12:28:14 -07002050 if ( AUTO_CHANNEL_SELECT != pConfig->channel )
2051 {
2052 sme_SelectCBMode(hHal,
2053 sapConvertSapPhyModeToCsrPhyMode(pConfig->SapHw_mode),
2054 pConfig->channel);
2055 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002056 // ht_capab is not what the name conveys,this is used for protection bitmap
2057 pConfig->ht_capab =
2058 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
2059
2060 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
2061 {
2062 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
2063 return -EINVAL;
2064 }
2065
2066 //Uapsd Enabled Bit
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302067 pConfig->UapsdEnable =
Jeff Johnson295189b2012-06-20 16:38:30 -07002068 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
2069 //Enable OBSS protection
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302070 pConfig->obssProtEnabled =
2071 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
Jeff Johnson295189b2012-06-20 16:38:30 -07002072
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302073 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
Jeff Johnson295189b2012-06-20 16:38:30 -07002074 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302075 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
Jeff Johnson295189b2012-06-20 16:38:30 -07002076 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
2077 (int)pConfig->channel);
2078 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302079 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
2080 pConfig->authType);
Jeff Johnson295189b2012-06-20 16:38:30 -07002081 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302082 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
Jeff Johnson295189b2012-06-20 16:38:30 -07002083 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
2084 pConfig->protEnabled, pConfig->obssProtEnabled);
2085
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302086 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07002087 {
2088 //Bss already started. just return.
2089 //TODO Probably it should update some beacon params.
2090 hddLog( LOGE, "Bss Already started...Ignore the request");
2091 EXIT();
2092 return 0;
2093 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302094
Jeff Johnson295189b2012-06-20 16:38:30 -07002095 pConfig->persona = pHostapdAdapter->device_mode;
2096
2097 pSapEventCallback = hdd_hostapd_SAPEventCB;
2098 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
2099 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
2100 {
2101 hddLog(LOGE,FL("SAP Start Bss fail\n"));
2102 return -EINVAL;
2103 }
2104
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302105 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07002106 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
2107
2108 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302109
Jeff Johnson295189b2012-06-20 16:38:30 -07002110 if (!VOS_IS_STATUS_SUCCESS(status))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302111 {
2112 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07002113 ("ERROR: HDD vos wait for single_event failed!!\n"));
2114 VOS_ASSERT(0);
2115 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302116
Jeff Johnson295189b2012-06-20 16:38:30 -07002117 //Succesfully started Bss update the state bit.
2118 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
2119
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002120#ifdef WLAN_FEATURE_P2P_DEBUG
2121 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
2122 {
2123 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
2124 {
2125 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
2126 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002127 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002128 }
2129 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
2130 {
2131 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
2132 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002133 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002134 }
2135 }
2136#endif
2137
Jeff Johnson295189b2012-06-20 16:38:30 -07002138 pHostapdState->bCommit = TRUE;
2139 EXIT();
2140
2141 return 0;
2142}
2143
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002144#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302145static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
2146 struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -07002147 struct beacon_parameters *params)
2148{
2149 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302150 hdd_context_t *pHddCtx;
2151 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002152
2153 ENTER();
2154
2155 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
2156
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302157 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2158 status = wlan_hdd_validate_context(pHddCtx);
2159
2160 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002161 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302162 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2163 "%s: HDD context is not valid", __func__);
2164 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002165 }
2166
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302167 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002168 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002169 )
2170 {
2171 beacon_data_t *old,*new;
2172
2173 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302174
Jeff Johnson295189b2012-06-20 16:38:30 -07002175 if (old)
2176 return -EALREADY;
2177
2178 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2179
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302180 if(status != VOS_STATUS_SUCCESS)
Jeff Johnson295189b2012-06-20 16:38:30 -07002181 {
2182 hddLog(VOS_TRACE_LEVEL_FATAL,
2183 "%s:Error!!! Allocating the new beacon\n",__func__);
2184 return -EINVAL;
2185 }
2186
2187 pAdapter->sessionCtx.ap.beacon = new;
2188
2189 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2190 }
2191
2192 EXIT();
2193 return status;
2194}
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302195
2196static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07002197 struct net_device *dev,
2198 struct beacon_parameters *params)
2199{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302200 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302201 hdd_context_t *pHddCtx;
2202 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002203
2204 ENTER();
2205
2206 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2207 __func__,pAdapter->device_mode);
2208
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302209 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2210 status = wlan_hdd_validate_context(pHddCtx);
2211
2212 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002213 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302214 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2215 "%s: HDD context is not valid", __func__);
2216 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002217 }
2218
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302219 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002220 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302221 )
Jeff Johnson295189b2012-06-20 16:38:30 -07002222 {
2223 beacon_data_t *old,*new;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302224
Jeff Johnson295189b2012-06-20 16:38:30 -07002225 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302226
Jeff Johnson295189b2012-06-20 16:38:30 -07002227 if (!old)
2228 return -ENOENT;
2229
2230 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2231
2232 if(status != VOS_STATUS_SUCCESS) {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302233 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -07002234 "%s: Error!!! Allocating the new beacon\n",__func__);
2235 return -EINVAL;
2236 }
2237
2238 pAdapter->sessionCtx.ap.beacon = new;
2239
2240 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2241 }
2242
2243 EXIT();
2244 return status;
2245}
2246
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002247#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
2248
2249#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002250static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
2251 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002252#else
2253static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
2254 struct net_device *dev)
2255#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002256{
2257 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07002258 hdd_context_t *pHddCtx = NULL;
2259 hdd_scaninfo_t *pScanInfo = NULL;
2260 hdd_adapter_t *staAdapter = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302261 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002262
2263 ENTER();
2264
2265 if (NULL == pAdapter)
2266 {
2267 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002268 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002269 return -ENODEV;
2270 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002271
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302272 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2273 status = wlan_hdd_validate_context(pHddCtx);
2274
2275 if (0 != status)
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002276 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302277 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2278 "%s: HDD context is not valid", __func__);
2279 return status;
Jeff Johnson4416a782013-03-25 14:17:50 -07002280 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002281
2282 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
2283 if (NULL == staAdapter)
2284 {
2285 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
2286 if (NULL == staAdapter)
2287 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302288 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002289 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002290 return -ENODEV;
2291 }
2292 }
2293
2294 pScanInfo = &pHddCtx->scan_info;
2295
Jeff Johnson295189b2012-06-20 16:38:30 -07002296 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2297 __func__,pAdapter->device_mode);
2298
Jeff Johnsone7245742012-09-05 17:12:55 -07002299 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
2300 {
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002301 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05302302 hdd_abort_mac_scan(staAdapter->pHddCtx, pAdapter->sessionId);
Jeff Johnsone7245742012-09-05 17:12:55 -07002303 status = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002304 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07002305 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
2306 if (!status)
2307 {
2308 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson902c9832012-12-10 14:28:09 -08002309 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002310 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07002311 VOS_ASSERT(pScanInfo->mScanPending);
2312 return 0;
2313 }
2314 }
2315
Jeff Johnson295189b2012-06-20 16:38:30 -07002316 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002317 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002318 )
2319 {
2320 beacon_data_t *old;
2321
2322 old = pAdapter->sessionCtx.ap.beacon;
2323
2324 if (!old)
2325 return -ENOENT;
2326
Jeff Johnson295189b2012-06-20 16:38:30 -07002327 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002328
2329 mutex_lock(&pHddCtx->sap_lock);
2330 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2331 {
Jeff Johnson4416a782013-03-25 14:17:50 -07002332 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss(pHddCtx->pvosContext) ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07002333 {
2334 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2335
2336 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2337
2338 if (!VOS_IS_STATUS_SUCCESS(status))
2339 {
2340 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2341 ("ERROR: HDD vos wait for single_event failed!!\n"));
2342 VOS_ASSERT(0);
2343 }
2344 }
2345 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2346 }
2347 mutex_unlock(&pHddCtx->sap_lock);
2348
2349 if(status != VOS_STATUS_SUCCESS)
2350 {
2351 hddLog(VOS_TRACE_LEVEL_FATAL,
2352 "%s:Error!!! Stopping the BSS\n",__func__);
2353 return -EINVAL;
2354 }
2355
Jeff Johnson4416a782013-03-25 14:17:50 -07002356 if (ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002357 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
2358 ==eHAL_STATUS_FAILURE)
2359 {
2360 hddLog(LOGE,
2361 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
2362 }
2363
Jeff Johnson4416a782013-03-25 14:17:50 -07002364 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002365 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2366 eANI_BOOLEAN_FALSE) )
2367 {
2368 hddLog(LOGE,
2369 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
2370 }
2371
2372 // Reset WNI_CFG_PROBE_RSP Flags
2373 wlan_hdd_reset_prob_rspies(pAdapter);
2374
2375 pAdapter->sessionCtx.ap.beacon = NULL;
2376 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002377#ifdef WLAN_FEATURE_P2P_DEBUG
2378 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
2379 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
2380 {
2381 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
2382 "GO got removed");
2383 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
2384 }
2385#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002386 }
2387 EXIT();
2388 return status;
2389}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002390
2391#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2392
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302393static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2394 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002395 struct cfg80211_ap_settings *params)
2396{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302397 hdd_adapter_t *pAdapter;
2398 hdd_context_t *pHddCtx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302399 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002400
2401 ENTER();
2402
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302403 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002404 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302405 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302406 "%s: Device is Null", __func__);
2407 return -ENODEV;
2408 }
2409
2410 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2411 if (NULL == pAdapter)
2412 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302413 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302414 "%s: HDD adapter is Null", __func__);
2415 return -ENODEV;
2416 }
2417
2418 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2419 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302420 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302421 "%s: HDD adapter magic is invalid", __func__);
2422 return -ENODEV;
2423 }
2424
2425 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302426 status = wlan_hdd_validate_context(pHddCtx);
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302427
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302428 if (0 != status)
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302429 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302430 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2431 "%s: HDD context is not valid", __func__);
2432 return status;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302433 }
2434
2435 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2436 __func__, pAdapter->device_mode);
2437
2438 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002439 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002440 )
2441 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302442 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002443
2444 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302445
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002446 if (old)
2447 return -EALREADY;
2448
2449 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2450
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302451 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002452 {
2453 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302454 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002455 return -EINVAL;
2456 }
2457 pAdapter->sessionCtx.ap.beacon = new;
Viral Modi3a32cc52013-02-08 11:14:52 -08002458#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Yue Maf49ba872013-08-19 12:04:25 -07002459 wlan_hdd_cfg80211_set_channel(wiphy, dev,
2460#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2461 params->channel, params->channel_type);
2462#else
2463 params->chandef.chan, cfg80211_get_chandef_type(&(params->chandef)));
2464#endif
Viral Modi3a32cc52013-02-08 11:14:52 -08002465#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002466 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2467 params->ssid_len, params->hidden_ssid);
2468 }
2469
2470 EXIT();
2471 return status;
2472}
2473
2474
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302475static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002476 struct net_device *dev,
2477 struct cfg80211_beacon_data *params)
2478{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302479 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302480 hdd_context_t *pHddCtx;
2481 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002482
2483 ENTER();
2484
2485 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2486 __func__, pAdapter->device_mode);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302487
2488 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2489 status = wlan_hdd_validate_context(pHddCtx);
2490
2491 if (0 != status)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002492 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302493 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2494 "%s: HDD context is not valid", __func__);
2495 return status;
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002496 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002497
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302498 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002499 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302500 )
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002501 {
2502 beacon_data_t *old,*new;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302503
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002504 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302505
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002506 if (!old)
2507 return -ENOENT;
2508
2509 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2510
2511 if(status != VOS_STATUS_SUCCESS) {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302512 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002513 "%s: Error!!! Allocating the new beacon\n",__func__);
2514 return -EINVAL;
2515 }
2516
2517 pAdapter->sessionCtx.ap.beacon = new;
2518
2519 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2520 }
2521
2522 EXIT();
2523 return status;
2524}
2525
2526#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2527
Jeff Johnson295189b2012-06-20 16:38:30 -07002528
2529static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2530 struct net_device *dev,
2531 struct bss_parameters *params)
2532{
2533 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2534
2535 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302536
Jeff Johnson295189b2012-06-20 16:38:30 -07002537 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2538 __func__,pAdapter->device_mode);
2539
2540 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002541 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302542 )
Jeff Johnson295189b2012-06-20 16:38:30 -07002543 {
2544 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2545 * want to update this parameter */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302546 if (-1 != params->ap_isolate)
Jeff Johnson295189b2012-06-20 16:38:30 -07002547 {
2548 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302549 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002550 }
2551
2552 EXIT();
2553 return 0;
2554}
2555
2556/*
2557 * FUNCTION: wlan_hdd_cfg80211_change_iface
2558 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2559 */
2560int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2561 struct net_device *ndev,
2562 enum nl80211_iftype type,
2563 u32 *flags,
2564 struct vif_params *params
2565 )
2566{
2567 struct wireless_dev *wdev;
2568 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2569 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002570 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002571 tCsrRoamProfile *pRoamProfile = NULL;
2572 eCsrRoamBssType LastBSSType;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302573 hdd_config_t *pConfig = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002574 eMib_dot11DesiredBssType connectedBssType;
2575 VOS_STATUS status;
2576
2577 ENTER();
2578
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302579 status = wlan_hdd_validate_context(pHddCtx);
2580
2581 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07002582 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302583 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2584 "%s: HDD context is not valid", __func__);
2585 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002586 }
2587
2588 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2589 __func__, pAdapter->device_mode);
2590
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302591 pConfig = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07002592 wdev = ndev->ieee80211_ptr;
2593
2594#ifdef WLAN_BTAMP_FEATURE
2595 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2596 (NL80211_IFTYPE_ADHOC == type)||
2597 (NL80211_IFTYPE_AP == type)||
2598 (NL80211_IFTYPE_P2P_GO == type))
2599 {
2600 pHddCtx->isAmpAllowed = VOS_FALSE;
2601 // stop AMP traffic
2602 status = WLANBAP_StopAmp();
2603 if(VOS_STATUS_SUCCESS != status )
2604 {
2605 pHddCtx->isAmpAllowed = VOS_TRUE;
2606 hddLog(VOS_TRACE_LEVEL_FATAL,
2607 "%s: Failed to stop AMP", __func__);
2608 return -EINVAL;
2609 }
2610 }
2611#endif //WLAN_BTAMP_FEATURE
2612 /* Reset the current device mode bit mask*/
2613 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2614
2615 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07002616 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002617 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002618 )
2619 {
2620 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2621 pRoamProfile = &pWextState->roamProfile;
2622 LastBSSType = pRoamProfile->BSSType;
2623
2624 switch (type)
2625 {
2626 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002627 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002628 hddLog(VOS_TRACE_LEVEL_INFO,
2629 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2630 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002631#ifdef WLAN_FEATURE_11AC
2632 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2633 {
2634 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2635 }
2636#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302637 pRoamProfile->phyMode =
Jeff Johnsone7245742012-09-05 17:12:55 -07002638 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002639 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002640 //Check for sub-string p2p to confirm its a p2p interface
2641 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302642 {
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002643 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2644 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2645 }
2646 else
2647 {
2648 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002649 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002650 }
Madan Mohan Koyyalamudi81746922013-07-17 14:38:51 +05302651#ifdef FEATURE_WLAN_TDLS
2652 /* The open adapter for the p2p shall skip initializations in
2653 * tdls_init if the device mode is WLAN_HDD_P2P_DEVICE, for
2654 * TDLS is supported only on WLAN_HDD_P2P_CLIENT. Hence invoke
2655 * tdls_init when the change_iface sets the device mode to
2656 * WLAN_HDD_P2P_CLIENT.
2657 */
2658
2659 if ( pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2660 {
2661 if (0 != wlan_hdd_tdls_init (pAdapter))
2662 {
2663 return -EINVAL;
2664 }
2665 }
2666#endif
2667
Jeff Johnson295189b2012-06-20 16:38:30 -07002668 break;
2669 case NL80211_IFTYPE_ADHOC:
2670 hddLog(VOS_TRACE_LEVEL_INFO,
2671 "%s: setting interface Type to ADHOC", __func__);
2672 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2673 pRoamProfile->phyMode =
2674 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Shailender Karmuchia734f332013-04-19 14:02:48 -07002675 pAdapter->device_mode = WLAN_HDD_IBSS;
Jeff Johnson295189b2012-06-20 16:38:30 -07002676 wdev->iftype = type;
2677 break;
2678
2679 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002680 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002681 {
2682 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2683 "%s: setting interface Type to %s", __func__,
2684 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2685
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002686 //Cancel any remain on channel for GO mode
2687 if (NL80211_IFTYPE_P2P_GO == type)
2688 {
2689 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2690 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002691 if (NL80211_IFTYPE_AP == type)
2692 {
2693 /* As Loading WLAN Driver one interface being created for p2p device
2694 * address. This will take one HW STA and the max number of clients
2695 * that can connect to softAP will be reduced by one. so while changing
2696 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2697 * interface as it is not required in SoftAP mode.
2698 */
2699
2700 // Get P2P Adapter
2701 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2702
2703 if (pP2pAdapter)
2704 {
2705 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2706 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2707 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2708 }
2709 }
2710
Jeff Johnson295189b2012-06-20 16:38:30 -07002711 //De-init the adapter.
2712 hdd_stop_adapter( pHddCtx, pAdapter );
2713 hdd_deinit_adapter( pHddCtx, pAdapter );
2714 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
Jeff Johnson295189b2012-06-20 16:38:30 -07002715 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2716 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002717
2718 //Disable BMPS and IMPS if enabled
2719 //before starting Go
2720 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2721 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302722 if(VOS_STATUS_E_FAILURE ==
Jeff Johnson32d95a32012-09-10 13:15:23 -07002723 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2724 {
2725 //Fail to Exit BMPS
2726 VOS_ASSERT(0);
2727 }
2728 }
2729
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002730 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2731 (pConfig->apRandomBssidEnabled))
2732 {
2733 /* To meet Android requirements create a randomized
2734 MAC address of the form 02:1A:11:Fx:xx:xx */
2735 get_random_bytes(&ndev->dev_addr[3], 3);
2736 ndev->dev_addr[0] = 0x02;
2737 ndev->dev_addr[1] = 0x1A;
2738 ndev->dev_addr[2] = 0x11;
2739 ndev->dev_addr[3] |= 0xF0;
2740 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2741 VOS_MAC_ADDR_SIZE);
2742 pr_info("wlan: Generated HotSpot BSSID "
2743 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2744 ndev->dev_addr[0],
2745 ndev->dev_addr[1],
2746 ndev->dev_addr[2],
2747 ndev->dev_addr[3],
2748 ndev->dev_addr[4],
2749 ndev->dev_addr[5]);
2750 }
2751
Jeff Johnson295189b2012-06-20 16:38:30 -07002752 hdd_set_ap_ops( pAdapter->dev );
2753
2754 status = hdd_init_ap_mode(pAdapter);
2755 if(status != VOS_STATUS_SUCCESS)
2756 {
2757 hddLog(VOS_TRACE_LEVEL_FATAL,
2758 "%s: Error initializing the ap mode", __func__);
2759 return -EINVAL;
2760 }
2761 hdd_set_conparam(1);
2762
Jeff Johnson295189b2012-06-20 16:38:30 -07002763 /*interface type changed update in wiphy structure*/
2764 if(wdev)
2765 {
2766 wdev->iftype = type;
2767 pHddCtx->change_iface = type;
2768 }
2769 else
2770 {
2771 hddLog(VOS_TRACE_LEVEL_ERROR,
2772 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2773 return -EINVAL;
2774 }
2775 goto done;
2776 }
2777
2778 default:
2779 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2780 __func__);
2781 return -EOPNOTSUPP;
2782 }
2783 }
2784 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002785 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002786 )
2787 {
2788 switch(type)
2789 {
2790 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002791 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002792 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002793 hdd_stop_adapter( pHddCtx, pAdapter );
2794 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002795 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002796 //Check for sub-string p2p to confirm its a p2p interface
2797 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002798 {
2799 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2800 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2801 }
2802 else
2803 {
2804 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002805 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002806 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002807 hdd_set_conparam(0);
2808 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002809 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2810 hdd_set_station_ops( pAdapter->dev );
2811 status = hdd_init_station_mode( pAdapter );
2812 if( VOS_STATUS_SUCCESS != status )
2813 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002814 /* In case of JB, for P2P-GO, only change interface will be called,
2815 * This is the right place to enable back bmps_imps()
2816 */
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05302817 if (pHddCtx->hdd_wlan_suspended)
2818 {
2819 hdd_set_pwrparams(pHddCtx);
2820 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002821 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002822 goto done;
2823 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002824 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002825 wdev->iftype = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002826 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2827 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07002828 goto done;
2829 default:
2830 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2831 __func__);
2832 return -EOPNOTSUPP;
2833
2834 }
2835
2836 }
2837 else
2838 {
2839 return -EOPNOTSUPP;
2840 }
2841
2842
2843 if(pRoamProfile)
2844 {
2845 if ( LastBSSType != pRoamProfile->BSSType )
2846 {
2847 /*interface type changed update in wiphy structure*/
2848 wdev->iftype = type;
2849
2850 /*the BSS mode changed, We need to issue disconnect
2851 if connected or in IBSS disconnect state*/
2852 if ( hdd_connGetConnectedBssType(
2853 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2854 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2855 {
2856 /*need to issue a disconnect to CSR.*/
2857 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2858 if( eHAL_STATUS_SUCCESS ==
2859 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2860 pAdapter->sessionId,
2861 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2862 {
2863 wait_for_completion_interruptible_timeout(
2864 &pAdapter->disconnect_comp_var,
2865 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2866 }
2867 }
2868 }
2869 }
2870
2871done:
2872 /*set bitmask based on updated value*/
2873 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
Leo Chang6fe1f922013-06-07 19:21:24 -07002874
2875 /* Only STA mode support TM now
2876 * all other mode, TM feature should be disabled */
2877 if ( (pHddCtx->cfg_ini->thermalMitigationEnable) &&
2878 (~VOS_STA & pHddCtx->concurrency_mode) )
2879 {
2880 hddDevTmLevelChangedHandler(pHddCtx->parent_dev, 0);
2881 }
2882
Jeff Johnson295189b2012-06-20 16:38:30 -07002883#ifdef WLAN_BTAMP_FEATURE
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302884 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07002885 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2886 {
2887 //we are ok to do AMP
2888 pHddCtx->isAmpAllowed = VOS_TRUE;
2889 }
2890#endif //WLAN_BTAMP_FEATURE
2891 EXIT();
2892 return 0;
2893}
2894
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002895#ifdef FEATURE_WLAN_TDLS
2896static int wlan_hdd_tdls_add_station(struct wiphy *wiphy,
2897 struct net_device *dev, u8 *mac, bool update, tCsrStaParams *StaParams)
2898{
2899 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2900 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2901 VOS_STATUS status;
Hoonki Lee5305c3a2013-04-29 23:28:59 -07002902 hddTdlsPeer_t *pTdlsPeer;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002903
2904 ENTER();
2905
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05302906 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002907 {
2908 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2909 "Invalid arguments");
2910 return -EINVAL;
2911 }
Hoonki Lee27511902013-03-14 18:19:06 -07002912
2913 if ((eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) ||
2914 (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode))
2915 {
2916 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2917 "%s: TDLS mode is disabled OR not enabled in FW."
2918 MAC_ADDRESS_STR " Request declined.",
2919 __func__, MAC_ADDR_ARRAY(mac));
2920 return -ENOTSUPP;
2921 }
2922
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002923 if (pHddCtx->isLogpInProgress)
2924 {
2925 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2926 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07002927 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002928 return -EBUSY;
2929 }
2930
Hoonki Lee5305c3a2013-04-29 23:28:59 -07002931 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac);
2932
2933 if ( NULL == pTdlsPeer ) {
2934 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2935 "%s: " MAC_ADDRESS_STR " (update %d) not exist. return invalid",
2936 __func__, MAC_ADDR_ARRAY(mac), update);
2937 return -EINVAL;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002938 }
Hoonki Lee5305c3a2013-04-29 23:28:59 -07002939
2940 /* in add station, we accept existing valid staId if there is */
2941 if ((0 == update) &&
2942 ((pTdlsPeer->link_status >= eTDLS_LINK_CONNECTING) ||
2943 (TDLS_STA_INDEX_VALID(pTdlsPeer->staId))))
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002944 {
Hoonki Lee5305c3a2013-04-29 23:28:59 -07002945 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002946 "%s: " MAC_ADDRESS_STR
Hoonki Lee5305c3a2013-04-29 23:28:59 -07002947 " link_status %d. staId %d. add station ignored.",
2948 __func__, MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status, pTdlsPeer->staId);
2949 return 0;
2950 }
2951 /* in change station, we accept only when staId is valid */
2952 if ((1 == update) &&
2953 ((pTdlsPeer->link_status > eTDLS_LINK_CONNECTING) ||
2954 (!TDLS_STA_INDEX_VALID(pTdlsPeer->staId))))
2955 {
2956 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2957 "%s: " MAC_ADDRESS_STR
2958 " link status %d. staId %d. change station %s.",
2959 __func__, MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status, pTdlsPeer->staId,
2960 (TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) ? "ignored" : "declined");
2961 return (TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) ? 0 : -EPERM;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002962 }
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002963
2964 /* when others are on-going, we want to change link_status to idle */
Hoonki Leefb8df672013-04-10 18:20:34 -07002965 if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, mac, TRUE, TRUE))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002966 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002967 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2968 "%s: " MAC_ADDRESS_STR
2969 " TDLS setup is ongoing. Request declined.",
2970 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002971 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002972 }
2973
2974 /* first to check if we reached to maximum supported TDLS peer.
2975 TODO: for now, return -EPERM looks working fine,
2976 but need to check if any other errno fit into this category.*/
2977 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
2978 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002979 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2980 "%s: " MAC_ADDRESS_STR
2981 " TDLS Max peer already connected. Request declined.",
2982 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002983 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002984 }
2985 else
2986 {
2987 hddTdlsPeer_t *pTdlsPeer;
2988 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002989 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002990 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002991 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2992 "%s: " MAC_ADDRESS_STR " already connected. Request declined.",
2993 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002994 return -EPERM;
2995 }
2996 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002997 if (0 == update)
2998 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_CONNECTING);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002999
Jeff Johnsond75fe012013-04-06 10:53:06 -07003000 /* debug code */
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05303001 if (NULL != StaParams)
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003002 {
3003 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3004 "%s: TDLS Peer Parameters.", __func__);
Hoonki Lee66b75f32013-04-16 18:30:07 -07003005 if(StaParams->htcap_present)
3006 {
3007 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3008 "ht_capa->cap_info: %0x", StaParams->HTCap.capInfo);
3009 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3010 "ht_capa->extended_capabilities: %0x",
3011 StaParams->HTCap.extendedHtCapInfo);
3012 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003013 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3014 "params->capability: %0x",StaParams->capability);
3015 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3016 "params->ext_capab_len: %0x",StaParams->extn_capability);
Hoonki Lee66b75f32013-04-16 18:30:07 -07003017 if(StaParams->vhtcap_present)
3018 {
3019 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3020 "rxMcsMap %x rxHighest %x txMcsMap %x txHighest %x",
3021 StaParams->VHTCap.suppMcs.rxMcsMap, StaParams->VHTCap.suppMcs.rxHighest,
3022 StaParams->VHTCap.suppMcs.txMcsMap, StaParams->VHTCap.suppMcs.txHighest);
3023 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003024 {
3025 int i = 0;
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003026 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "Supported rates:");
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003027 for (i = 0; i < sizeof(StaParams->supported_rates); i++)
3028 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3029 "[%d]: %x ", i, StaParams->supported_rates[i]);
3030 }
Jeff Johnsond75fe012013-04-06 10:53:06 -07003031 } /* end debug code */
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05303032 else if ((1 == update) && (NULL == StaParams))
3033 {
3034 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3035 "%s : update is true, but staParams is NULL. Error!", __func__);
3036 return -EPERM;
3037 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003038
3039 INIT_COMPLETION(pAdapter->tdls_add_station_comp);
3040
3041 if (!update)
3042 {
3043 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
3044 pAdapter->sessionId, mac);
3045 }
3046 else
3047 {
3048 status = sme_ChangeTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
3049 pAdapter->sessionId, mac, StaParams);
3050 }
3051
3052 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_add_station_comp,
3053 msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
3054
3055 if (!status)
3056 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003057 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003058 "%s: timeout waiting for tdls add station indication",
3059 __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07003060 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003061 }
3062 if ( eHAL_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus)
3063 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003064 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003065 "%s: Add Station is unsucessful", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07003066 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003067 }
3068
3069 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07003070
3071error:
3072 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
3073 return -EPERM;
3074
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003075}
3076#endif
3077
Jeff Johnson295189b2012-06-20 16:38:30 -07003078static int wlan_hdd_change_station(struct wiphy *wiphy,
3079 struct net_device *dev,
3080 u8 *mac,
3081 struct station_parameters *params)
3082{
3083 VOS_STATUS status = VOS_STATUS_SUCCESS;
3084 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Gopichand Nakkala29149562013-05-10 21:43:41 +05303085 hdd_context_t *pHddCtx;
3086 hdd_station_ctx_t *pHddStaCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003087 v_MACADDR_t STAMacAddress;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003088#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003089 tCsrStaParams StaParams = {0};
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003090 tANI_U8 isBufSta = 0;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003091#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003092 ENTER();
3093
Gopichand Nakkala29149562013-05-10 21:43:41 +05303094 if ((NULL == pAdapter))
3095 {
3096 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3097 "invalid adapter ");
3098 return -EINVAL;
3099 }
3100
3101 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3102 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3103
3104 if ((NULL == pHddCtx) || (NULL == pHddStaCtx))
3105 {
3106 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3107 "invalid HDD state or HDD station context");
3108 return -EINVAL;
3109 }
3110
3111 if (pHddCtx->isLogpInProgress)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003112 {
3113 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3114 "%s:LOGP in Progress. Ignore!!!", __func__);
3115 return -EAGAIN;
3116 }
3117
Jeff Johnson295189b2012-06-20 16:38:30 -07003118 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
3119
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003120 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3121 || (pAdapter->device_mode == WLAN_HDD_P2P_GO))
Jeff Johnson295189b2012-06-20 16:38:30 -07003122 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003123 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
Jeff Johnson295189b2012-06-20 16:38:30 -07003124 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303125 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
Jeff Johnson295189b2012-06-20 16:38:30 -07003126 WLANTL_STA_AUTHENTICATED);
3127
Gopichand Nakkala29149562013-05-10 21:43:41 +05303128 if (status != VOS_STATUS_SUCCESS)
3129 {
3130 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3131 "%s: Not able to change TL state to AUTHENTICATED", __func__);
3132 return -EINVAL;
3133 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003134 }
3135 }
Hoonki Leea6d49be2013-04-05 09:43:25 -07003136 else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3137 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) {
Gopichand Nakkala29149562013-05-10 21:43:41 +05303138#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003139 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
3140 StaParams.capability = params->capability;
3141 StaParams.uapsd_queues = params->uapsd_queues;
3142 StaParams.max_sp = params->max_sp;
3143
3144 if (0 != params->ext_capab_len)
3145 vos_mem_copy(StaParams.extn_capability, params->ext_capab,
3146 sizeof(StaParams.extn_capability));
3147
3148 if (NULL != params->ht_capa)
Hoonki Lee66b75f32013-04-16 18:30:07 -07003149 {
3150 StaParams.htcap_present = 1;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003151 vos_mem_copy(&StaParams.HTCap, params->ht_capa, sizeof(tSirHTCap));
Hoonki Lee66b75f32013-04-16 18:30:07 -07003152 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003153
3154 StaParams.supported_rates_len = params->supported_rates_len;
3155
3156 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
3157 * The supported_rates array , for all the structures propogating till Add Sta
3158 * to the firmware has to be modified , if the supplicant (ieee80211) is
3159 * modified to send more rates.
3160 */
3161
3162 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
3163 */
3164 if (StaParams.supported_rates_len > SIR_MAC_MAX_SUPP_RATES)
3165 StaParams.supported_rates_len = SIR_MAC_MAX_SUPP_RATES;
3166
3167 if (0 != StaParams.supported_rates_len) {
3168 int i = 0;
3169 vos_mem_copy(StaParams.supported_rates, params->supported_rates,
3170 StaParams.supported_rates_len);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003171 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003172 "Supported Rates with Length %d", StaParams.supported_rates_len);
3173 for (i=0; i < StaParams.supported_rates_len; i++)
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003174 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003175 "[%d]: %0x", i, StaParams.supported_rates[i]);
3176 }
3177
3178 if (NULL != params->vht_capa)
Hoonki Lee66b75f32013-04-16 18:30:07 -07003179 {
3180 StaParams.vhtcap_present = 1;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003181 vos_mem_copy(&StaParams.VHTCap, params->vht_capa, sizeof(tSirVHTCap));
Hoonki Lee66b75f32013-04-16 18:30:07 -07003182 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003183
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003184 if (0 != params->ext_capab_len ) {
3185 /*Define A Macro : TODO Sunil*/
3186 if ((1<<4) & StaParams.extn_capability[3]) {
3187 isBufSta = 1;
3188 }
3189 }
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303190 status = wlan_hdd_tdls_set_peer_caps( pAdapter, mac, params->uapsd_queues,
3191 params->max_sp, isBufSta);
3192 if (VOS_STATUS_SUCCESS != status) {
3193 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3194 "%s: wlan_hdd_tdls_set_peer_caps failed!", __func__);
3195 return -EINVAL;
3196 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003197 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 1, &StaParams);
3198
3199 if (VOS_STATUS_SUCCESS != status) {
3200 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3201 "%s: sme_ChangeTdlsPeerSta failed!", __func__);
3202 return -EINVAL;
3203 }
3204 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003205#endif
Gopichand Nakkala6239acd2013-06-14 14:48:00 +05303206 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003207 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003208 return status;
3209}
3210
3211/*
Jeff Johnson295189b2012-06-20 16:38:30 -07003212 * FUNCTION: wlan_hdd_cfg80211_add_key
3213 * This function is used to initialize the key information
3214 */
3215#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003216static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003217 struct net_device *ndev,
3218 u8 key_index, bool pairwise,
3219 const u8 *mac_addr,
3220 struct key_params *params
3221 )
3222#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003223static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003224 struct net_device *ndev,
3225 u8 key_index, const u8 *mac_addr,
3226 struct key_params *params
3227 )
3228#endif
3229{
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003230 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003231 tCsrRoamSetKey setKey;
3232 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303233 int status;
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003234 v_U32_t roamId= 0xFF;
3235 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003236 hdd_hostapd_state_t *pHostapdState;
3237 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003238 eHalStatus halStatus;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303239 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003240
3241 ENTER();
3242
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303243 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3244 status = wlan_hdd_validate_context(pHddCtx);
3245
3246 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003247 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303248 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3249 "%s: HDD context is not valid", __func__);
3250 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003251 }
3252
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003253 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
3254 __func__, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003255
3256 if (CSR_MAX_NUM_KEY <= key_index)
3257 {
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003258 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003259 key_index);
3260
3261 return -EINVAL;
3262 }
3263
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003264 if (CSR_MAX_KEY_LEN < params->key_len)
3265 {
3266 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key length %d", __func__,
3267 params->key_len);
3268
3269 return -EINVAL;
3270 }
3271
3272 hddLog(VOS_TRACE_LEVEL_INFO,
3273 "%s: called with key index = %d & key length %d",
3274 __func__, key_index, params->key_len);
Jeff Johnson295189b2012-06-20 16:38:30 -07003275
3276 /*extract key idx, key len and key*/
3277 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3278 setKey.keyId = key_index;
3279 setKey.keyLength = params->key_len;
3280 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
3281
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003282 switch (params->cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07003283 {
3284 case WLAN_CIPHER_SUITE_WEP40:
3285 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
3286 break;
3287
3288 case WLAN_CIPHER_SUITE_WEP104:
3289 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
3290 break;
3291
3292 case WLAN_CIPHER_SUITE_TKIP:
3293 {
3294 u8 *pKey = &setKey.Key[0];
3295 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
3296
3297 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
3298
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003299 /*Supplicant sends the 32bytes key in this order
Jeff Johnson295189b2012-06-20 16:38:30 -07003300
3301 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003302 | Tk1 |TX-MIC | RX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003303 |--------------|----------|----------|
3304 <---16bytes---><--8bytes--><--8bytes-->
3305
3306 */
3307 /*Sme expects the 32 bytes key to be in the below order
3308
3309 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003310 | Tk1 |RX-MIC | TX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003311 |--------------|----------|----------|
3312 <---16bytes---><--8bytes--><--8bytes-->
3313 */
3314 /* Copy the Temporal Key 1 (TK1) */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003315 vos_mem_copy(pKey, params->key, 16);
Jeff Johnson295189b2012-06-20 16:38:30 -07003316
3317 /*Copy the rx mic first*/
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003318 vos_mem_copy(&pKey[16], &params->key[24], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003319
3320 /*Copy the tx mic */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003321 vos_mem_copy(&pKey[24], &params->key[16], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003322
3323
3324 break;
3325 }
3326
3327 case WLAN_CIPHER_SUITE_CCMP:
3328 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
3329 break;
3330
3331#ifdef FEATURE_WLAN_WAPI
3332 case WLAN_CIPHER_SUITE_SMS4:
3333 {
3334 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3335 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
3336 params->key, params->key_len);
3337 return 0;
3338 }
3339#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003340
Jeff Johnson295189b2012-06-20 16:38:30 -07003341#ifdef FEATURE_WLAN_CCX
3342 case WLAN_CIPHER_SUITE_KRK:
3343 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
3344 break;
3345#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003346
3347#ifdef WLAN_FEATURE_11W
3348 case WLAN_CIPHER_SUITE_AES_CMAC:
3349 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
Chet Lanctot3b5158a2013-03-31 16:45:21 -07003350 break;
Chet Lanctot186b5732013-03-18 10:26:30 -07003351#endif
3352
Jeff Johnson295189b2012-06-20 16:38:30 -07003353 default:
3354 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
3355 __func__, params->cipher);
3356 return -EOPNOTSUPP;
3357 }
3358
3359 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
3360 __func__, setKey.encType);
3361
Shailender Karmuchi642e9812013-05-30 14:34:49 -07003362 if (
Jeff Johnson295189b2012-06-20 16:38:30 -07003363#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3364 (!pairwise)
3365#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003366 (!mac_addr || is_broadcast_ether_addr(mac_addr))
Jeff Johnson295189b2012-06-20 16:38:30 -07003367#endif
Shailender Karmuchi642e9812013-05-30 14:34:49 -07003368 )
3369 {
3370 /* set group key*/
3371 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3372 "%s- %d: setting Broadcast key",
3373 __func__, __LINE__);
3374 setKey.keyDirection = eSIR_RX_ONLY;
3375 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3376 }
3377 else
3378 {
3379 /* set pairwise key*/
3380 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3381 "%s- %d: setting pairwise key",
3382 __func__, __LINE__);
3383 setKey.keyDirection = eSIR_TX_RX;
3384 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3385 }
3386 if ((WLAN_HDD_IBSS == pAdapter->device_mode) && !pairwise)
3387 {
3388 setKey.keyDirection = eSIR_TX_RX;
3389 /*Set the group key*/
3390 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3391 pAdapter->sessionId, &setKey, &roamId );
Jeff Johnson295189b2012-06-20 16:38:30 -07003392
Shailender Karmuchi642e9812013-05-30 14:34:49 -07003393 if ( 0 != status )
3394 {
3395 hddLog(VOS_TRACE_LEVEL_ERROR,
3396 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3397 return -EINVAL;
3398 }
3399 /*Save the keys here and call sme_RoamSetKey for setting
3400 the PTK after peer joins the IBSS network*/
3401 vos_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
3402 &setKey, sizeof(tCsrRoamSetKey));
3403 return status;
3404 }
Gopichand Nakkala29149562013-05-10 21:43:41 +05303405 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) ||
3406 (pAdapter->device_mode == WLAN_HDD_P2P_GO))
3407 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003408 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003409 if( pHostapdState->bssState == BSS_START )
3410 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003411 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3412
3413 if ( status != eHAL_STATUS_SUCCESS )
3414 {
3415 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3416 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3417 __LINE__, status );
3418 }
3419 }
3420
3421 /* Saving WEP keys */
3422 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
3423 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
3424 {
3425 //Save the wep key in ap context. Issue setkey after the BSS is started.
3426 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3427 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
3428 }
3429 else
3430 {
3431 //Save the key in ap context. Issue setkey after the BSS is started.
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003432 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003433 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
3434 }
3435 }
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003436 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
3437 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) )
Jeff Johnson295189b2012-06-20 16:38:30 -07003438 {
3439 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3440 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3441
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303442#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3443 if (!pairwise)
3444#else
3445 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
3446#endif
3447 {
3448 /* set group key*/
3449 if (pHddStaCtx->roam_info.deferKeyComplete)
3450 {
3451 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3452 "%s- %d: Perform Set key Complete",
3453 __func__, __LINE__);
3454 hdd_PerformRoamSetKeyComplete(pAdapter);
3455 }
3456 }
3457
Jeff Johnson295189b2012-06-20 16:38:30 -07003458 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
3459
Venkata Prathyusha Kuntupalliee2ce712013-01-17 14:09:24 -08003460 pWextState->roamProfile.Keys.defaultIndex = key_index;
3461
3462
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003463 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07003464 params->key, params->key_len);
3465
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303466
Jeff Johnson295189b2012-06-20 16:38:30 -07003467 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3468
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303469 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07003470 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303471 __func__, setKey.peerMac[0], setKey.peerMac[1],
3472 setKey.peerMac[2], setKey.peerMac[3],
3473 setKey.peerMac[4], setKey.peerMac[5],
Jeff Johnson295189b2012-06-20 16:38:30 -07003474 setKey.keyDirection);
3475
3476 vos_status = wlan_hdd_check_ula_done(pAdapter);
3477
3478 if ( vos_status != VOS_STATUS_SUCCESS )
3479 {
3480 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3481 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
3482 __LINE__, vos_status );
3483
3484 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3485
3486 return -EINVAL;
3487
3488 }
3489
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003490#ifdef WLAN_FEATURE_VOWIFI_11R
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303491 /* The supplicant may attempt to set the PTK once pre-authentication
3492 is done. Save the key in the UMAC and include it in the ADD BSS
3493 request */
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003494 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303495 if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS )
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003496 {
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303497 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3498 "%s: Update PreAuth Key success", __func__);
3499 return 0;
3500 }
3501 else if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_FAILED )
3502 {
3503 hddLog(VOS_TRACE_LEVEL_ERROR,
3504 "%s: Update PreAuth Key failed", __func__);
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303505 return -EINVAL;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003506 }
3507#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07003508
3509 /* issue set key request to SME*/
3510 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3511 pAdapter->sessionId, &setKey, &roamId );
3512
3513 if ( 0 != status )
3514 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303515 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003516 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3517 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3518 return -EINVAL;
3519 }
3520
3521
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303522 /* in case of IBSS as there was no information available about WEP keys during
3523 * IBSS join, group key intialized with NULL key, so re-initialize group key
Jeff Johnson295189b2012-06-20 16:38:30 -07003524 * with correct value*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303525 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
3526 !( ( IW_AUTH_KEY_MGMT_802_1X
3527 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
Jeff Johnson295189b2012-06-20 16:38:30 -07003528 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3529 )
3530 &&
3531 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3532 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3533 )
3534 )
3535 {
3536 setKey.keyDirection = eSIR_RX_ONLY;
3537 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3538
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303539 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07003540 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303541 __func__, setKey.peerMac[0], setKey.peerMac[1],
3542 setKey.peerMac[2], setKey.peerMac[3],
3543 setKey.peerMac[4], setKey.peerMac[5],
Jeff Johnson295189b2012-06-20 16:38:30 -07003544 setKey.keyDirection);
3545
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303546 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07003547 pAdapter->sessionId, &setKey, &roamId );
3548
3549 if ( 0 != status )
3550 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303551 hddLog(VOS_TRACE_LEVEL_ERROR,
3552 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07003553 __func__, status);
3554 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3555 return -EINVAL;
3556 }
3557 }
3558 }
3559
3560 return 0;
3561}
3562
3563/*
3564 * FUNCTION: wlan_hdd_cfg80211_get_key
3565 * This function is used to get the key information
3566 */
3567#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303568static int wlan_hdd_cfg80211_get_key(
3569 struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003570 struct net_device *ndev,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303571 u8 key_index, bool pairwise,
Jeff Johnson295189b2012-06-20 16:38:30 -07003572 const u8 *mac_addr, void *cookie,
3573 void (*callback)(void *cookie, struct key_params*)
3574 )
3575#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303576static int wlan_hdd_cfg80211_get_key(
3577 struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003578 struct net_device *ndev,
3579 u8 key_index, const u8 *mac_addr, void *cookie,
3580 void (*callback)(void *cookie, struct key_params*)
3581 )
3582#endif
3583{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303584 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003585 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3586 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
3587 struct key_params params;
3588
3589 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303590
Jeff Johnson295189b2012-06-20 16:38:30 -07003591 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3592 __func__,pAdapter->device_mode);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303593
Jeff Johnson295189b2012-06-20 16:38:30 -07003594 memset(&params, 0, sizeof(params));
3595
3596 if (CSR_MAX_NUM_KEY <= key_index)
3597 {
3598 return -EINVAL;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303599 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003600
3601 switch(pRoamProfile->EncryptionType.encryptionType[0])
3602 {
3603 case eCSR_ENCRYPT_TYPE_NONE:
3604 params.cipher = IW_AUTH_CIPHER_NONE;
3605 break;
3606
3607 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3608 case eCSR_ENCRYPT_TYPE_WEP40:
3609 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3610 break;
3611
3612 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3613 case eCSR_ENCRYPT_TYPE_WEP104:
3614 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3615 break;
3616
3617 case eCSR_ENCRYPT_TYPE_TKIP:
3618 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3619 break;
3620
3621 case eCSR_ENCRYPT_TYPE_AES:
3622 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3623 break;
3624
3625 default:
3626 params.cipher = IW_AUTH_CIPHER_NONE;
3627 break;
3628 }
3629
3630 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3631 params.seq_len = 0;
3632 params.seq = NULL;
3633 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3634 callback(cookie, &params);
3635 return 0;
3636}
3637
3638/*
3639 * FUNCTION: wlan_hdd_cfg80211_del_key
3640 * This function is used to delete the key information
3641 */
3642#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303643static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003644 struct net_device *ndev,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303645 u8 key_index,
3646 bool pairwise,
Jeff Johnson295189b2012-06-20 16:38:30 -07003647 const u8 *mac_addr
3648 )
3649#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303650static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003651 struct net_device *ndev,
3652 u8 key_index,
3653 const u8 *mac_addr
3654 )
3655#endif
3656{
3657 int status = 0;
3658
3659 //This code needs to be revisited. There is sme_removeKey API, we should
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303660 //plan to use that. After the change to use correct index in setkey,
Jeff Johnson295189b2012-06-20 16:38:30 -07003661 //it is observed that this is invalidating peer
3662 //key index whenever re-key is done. This is affecting data link.
3663 //It should be ok to ignore del_key.
3664#if 0
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303665 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3666 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003667 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3668 tCsrRoamSetKey setKey;
3669 v_U32_t roamId= 0xFF;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303670
Jeff Johnson295189b2012-06-20 16:38:30 -07003671 ENTER();
3672
3673 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3674 __func__,pAdapter->device_mode);
3675
3676 if (CSR_MAX_NUM_KEY <= key_index)
3677 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303678 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003679 key_index);
3680
3681 return -EINVAL;
3682 }
3683
3684 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3685 setKey.keyId = key_index;
3686
3687 if (mac_addr)
3688 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3689 else
3690 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3691
3692 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3693
3694 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003695 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303696 )
3697 {
3698
3699 hdd_hostapd_state_t *pHostapdState =
Jeff Johnson295189b2012-06-20 16:38:30 -07003700 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3701 if( pHostapdState->bssState == BSS_START)
3702 {
3703 status = WLANSAP_SetKeySta( pVosContext, &setKey);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303704
Jeff Johnson295189b2012-06-20 16:38:30 -07003705 if ( status != eHAL_STATUS_SUCCESS )
3706 {
3707 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3708 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3709 __LINE__, status );
3710 }
3711 }
3712 }
3713 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303714 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003715 )
3716 {
3717 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3718
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303719 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3720
3721 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07003722 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303723 __func__, setKey.peerMac[0], setKey.peerMac[1],
3724 setKey.peerMac[2], setKey.peerMac[3],
Jeff Johnson295189b2012-06-20 16:38:30 -07003725 setKey.peerMac[4], setKey.peerMac[5]);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303726 if(pAdapter->sessionCtx.station.conn_info.connState ==
3727 eConnectionState_Associated)
Jeff Johnson295189b2012-06-20 16:38:30 -07003728 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303729 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07003730 pAdapter->sessionId, &setKey, &roamId );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303731
Jeff Johnson295189b2012-06-20 16:38:30 -07003732 if ( 0 != status )
3733 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303734 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003735 "%s: sme_RoamSetKey failure, returned %d",
3736 __func__, status);
3737 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3738 return -EINVAL;
3739 }
3740 }
3741 }
3742#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003743 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003744 return status;
3745}
3746
3747/*
3748 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3749 * This function is used to set the default tx key index
3750 */
3751#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3752static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3753 struct net_device *ndev,
3754 u8 key_index,
3755 bool unicast, bool multicast)
3756#else
3757static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3758 struct net_device *ndev,
3759 u8 key_index)
3760#endif
3761{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303762 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303763 int status;
Gopichand Nakkala29149562013-05-10 21:43:41 +05303764 hdd_wext_state_t *pWextState;
3765 hdd_station_ctx_t *pHddStaCtx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303766 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003767
3768 ENTER();
3769
Gopichand Nakkala29149562013-05-10 21:43:41 +05303770 if ((NULL == pAdapter))
3771 {
3772 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3773 "invalid adapter");
3774 return -EINVAL;
3775 }
3776
3777 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3778 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3779
3780 if ((NULL == pWextState) || (NULL == pHddStaCtx))
3781 {
3782 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3783 "invalid Wext state or HDD context");
3784 return -EINVAL;
3785 }
3786
Jeff Johnson295189b2012-06-20 16:38:30 -07003787 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3788 __func__,pAdapter->device_mode, key_index);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303789
Jeff Johnson295189b2012-06-20 16:38:30 -07003790 if (CSR_MAX_NUM_KEY <= key_index)
3791 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303792 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003793 key_index);
3794
3795 return -EINVAL;
3796 }
3797
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303798 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3799 status = wlan_hdd_validate_context(pHddCtx);
3800
3801 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003802 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303803 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3804 "%s: HDD context is not valid", __func__);
3805 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003806 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303807
Jeff Johnson295189b2012-06-20 16:38:30 -07003808 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003809 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303810 )
Jeff Johnson295189b2012-06-20 16:38:30 -07003811 {
Gopichand Nakkala29149562013-05-10 21:43:41 +05303812 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
Jeff Johnson295189b2012-06-20 16:38:30 -07003813 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303814 (eCSR_ENCRYPT_TYPE_AES !=
Jeff Johnson295189b2012-06-20 16:38:30 -07003815 pWextState->roamProfile.EncryptionType.encryptionType[0])
3816 )
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303817 {
3818 /* if default key index is not same as previous one,
Jeff Johnson295189b2012-06-20 16:38:30 -07003819 * then update the default key index */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303820
Jeff Johnson295189b2012-06-20 16:38:30 -07003821 tCsrRoamSetKey setKey;
3822 v_U32_t roamId= 0xFF;
3823 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303824
3825 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07003826 __func__, key_index);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303827
Jeff Johnson295189b2012-06-20 16:38:30 -07003828 Keys->defaultIndex = (u8)key_index;
3829 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3830 setKey.keyId = key_index;
3831 setKey.keyLength = Keys->KeyLength[key_index];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303832
3833 vos_mem_copy(&setKey.Key[0],
3834 &Keys->KeyMaterial[key_index][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07003835 Keys->KeyLength[key_index]);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303836
Gopichand Nakkala29149562013-05-10 21:43:41 +05303837 setKey.keyDirection = eSIR_TX_RX;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303838
3839 vos_mem_copy(setKey.peerMac,
Jeff Johnson295189b2012-06-20 16:38:30 -07003840 &pHddStaCtx->conn_info.bssId[0],
3841 WNI_CFG_BSSID_LEN);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303842
Gopichand Nakkala29149562013-05-10 21:43:41 +05303843 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
3844 pWextState->roamProfile.EncryptionType.encryptionType[0] ==
3845 eCSR_ENCRYPT_TYPE_WEP104)
3846 {
3847 /*In the case of dynamic wep supplicant hardcodes DWEP type to eCSR_ENCRYPT_TYPE_WEP104
3848 even though ap is configured for WEP-40 encryption. In this canse the key length
3849 is 5 but the encryption type is 104 hence checking the key langht(5) and encryption
3850 type(104) and switching encryption type to 40*/
3851 pWextState->roamProfile.EncryptionType.encryptionType[0] =
3852 eCSR_ENCRYPT_TYPE_WEP40;
3853 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
3854 eCSR_ENCRYPT_TYPE_WEP40;
3855 }
3856
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303857 setKey.encType =
Jeff Johnson295189b2012-06-20 16:38:30 -07003858 pWextState->roamProfile.EncryptionType.encryptionType[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303859
Jeff Johnson295189b2012-06-20 16:38:30 -07003860 /* issue set key request */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303861 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07003862 pAdapter->sessionId, &setKey, &roamId );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303863
Jeff Johnson295189b2012-06-20 16:38:30 -07003864 if ( 0 != status )
3865 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303866 hddLog(VOS_TRACE_LEVEL_ERROR,
3867 "%s: sme_RoamSetKey failed, returned %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003868 status);
3869 return -EINVAL;
3870 }
3871 }
3872 }
3873
3874 /* In SoftAp mode setting key direction for default mode */
3875 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3876 {
3877 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3878 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3879 (eCSR_ENCRYPT_TYPE_AES !=
3880 pWextState->roamProfile.EncryptionType.encryptionType[0])
3881 )
3882 {
3883 /* Saving key direction for default key index to TX default */
3884 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3885 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3886 }
3887 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303888
Jeff Johnson295189b2012-06-20 16:38:30 -07003889 return status;
3890}
3891
Jeff Johnson295189b2012-06-20 16:38:30 -07003892/*
3893 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3894 * This function is used to inform the BSS details to nl80211 interface.
3895 */
3896static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3897 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3898{
3899 struct net_device *dev = pAdapter->dev;
3900 struct wireless_dev *wdev = dev->ieee80211_ptr;
3901 struct wiphy *wiphy = wdev->wiphy;
3902 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3903 int chan_no;
3904 int ie_length;
3905 const char *ie;
3906 unsigned int freq;
3907 struct ieee80211_channel *chan;
3908 int rssi = 0;
3909 struct cfg80211_bss *bss = NULL;
3910
3911 ENTER();
3912
3913 if( NULL == pBssDesc )
3914 {
3915 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3916 return bss;
3917 }
3918
3919 chan_no = pBssDesc->channelId;
3920 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3921 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3922
3923 if( NULL == ie )
3924 {
3925 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3926 return bss;
3927 }
3928
3929#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3930 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3931 {
3932 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3933 }
3934 else
3935 {
3936 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3937 }
3938#else
3939 freq = ieee80211_channel_to_frequency(chan_no);
3940#endif
3941
3942 chan = __ieee80211_get_channel(wiphy, freq);
3943
3944 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3945 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3946 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3947 if (bss == NULL)
3948 {
3949 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3950
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303951 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3952 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
Jeff Johnson295189b2012-06-20 16:38:30 -07003953 pBssDesc->capabilityInfo,
3954 pBssDesc->beaconInterval, ie, ie_length,
3955 rssi, GFP_KERNEL ));
3956}
3957 else
3958 {
3959 return bss;
3960 }
3961}
3962
3963
3964
3965/*
3966 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3967 * This function is used to inform the BSS details to nl80211 interface.
3968 */
3969struct cfg80211_bss*
3970wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3971 tSirBssDescription *bss_desc
3972 )
3973{
3974 /*
3975 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3976 already exists in bss data base of cfg80211 for that particular BSS ID.
3977 Using cfg80211_inform_bss_frame to update the bss entry instead of
3978 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3979 now there is no possibility to get the mgmt(probe response) frame from PE,
3980 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3981 cfg80211_inform_bss_frame.
3982 */
3983 struct net_device *dev = pAdapter->dev;
3984 struct wireless_dev *wdev = dev->ieee80211_ptr;
3985 struct wiphy *wiphy = wdev->wiphy;
3986 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003987#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3988 qcom_ie_age *qie_age = NULL;
3989 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3990#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003991 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003992#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003993 const char *ie =
3994 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3995 unsigned int freq;
3996 struct ieee80211_channel *chan;
3997 struct ieee80211_mgmt *mgmt =
3998 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3999 struct cfg80211_bss *bss_status = NULL;
4000 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
4001 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07004002#ifdef WLAN_OPEN_SOURCE
4003 struct timespec ts;
4004#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004005
4006 ENTER();
4007
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07004008 if (!mgmt)
4009 return NULL;
4010
Jeff Johnson295189b2012-06-20 16:38:30 -07004011 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07004012
4013#ifdef WLAN_OPEN_SOURCE
4014 /* Android does not want the timestamp from the frame.
4015 Instead it wants a monotonic increasing value */
4016 get_monotonic_boottime(&ts);
4017 mgmt->u.probe_resp.timestamp =
4018 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
4019#else
4020 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07004021 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
4022 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07004023
4024#endif
4025
Jeff Johnson295189b2012-06-20 16:38:30 -07004026 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
4027 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08004028
4029#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
4030 /* GPS Requirement: need age ie per entry. Using vendor specific. */
4031 /* Assuming this is the last IE, copy at the end */
4032 ie_length -=sizeof(qcom_ie_age);
4033 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
4034 qie_age->element_id = QCOM_VENDOR_IE_ID;
4035 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
4036 qie_age->oui_1 = QCOM_OUI1;
4037 qie_age->oui_2 = QCOM_OUI2;
4038 qie_age->oui_3 = QCOM_OUI3;
4039 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
4040 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
4041#endif
4042
Jeff Johnson295189b2012-06-20 16:38:30 -07004043 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
Gopichand Nakkalad908ec82013-05-16 19:32:19 +05304044 if (bss_desc->fProbeRsp)
4045 {
4046 mgmt->frame_control |=
4047 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
4048 }
4049 else
4050 {
4051 mgmt->frame_control |=
4052 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
4053 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004054
4055#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304056 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07004057 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
4058 {
4059 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
4060 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304061 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07004062 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
4063
4064 {
4065 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
4066 }
4067 else
4068 {
4069 kfree(mgmt);
4070 return NULL;
4071 }
4072#else
4073 freq = ieee80211_channel_to_frequency(chan_no);
4074#endif
4075 chan = __ieee80211_get_channel(wiphy, freq);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08004076 /*when the band is changed on the fly using the GUI, three things are done
4077 * 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)
4078 * as part of the scan abort, message willbe queued to PE and we proceed with flushing and changinh the band.
4079 * pe will stop the scanning further and report back the results what ever it had till now by calling the call back function.
4080 * if the time between update band and scandone call back is sufficent enough the band change reflects in SME, SME validates the channels
4081 * and discards the channels correponding to previous band and calls back with zero bss results.
4082 * 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
4083 * all the channels correponding to previous band.this is due to race condition.but those channels are invalid to the new band and so
4084 * this function __ieee80211_get_channel will return NULL.Each time we report scan result with this pointer null warning kernel trace is printed.
4085 * if the scan results contain large number of APs continuosly kernel warning trace is printed and it will lead to apps watch dog bark.
4086 * So drop the bss and continue to next bss.
4087 */
4088 if(chan == NULL)
4089 {
4090 hddLog(VOS_TRACE_LEVEL_INFO, "%s chan pointer is NULL", __func__);
Chilam Ngc4244af2013-04-01 15:37:32 -07004091 kfree(mgmt);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08004092 return NULL;
4093 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004094 /*To keep the rssi icon of the connected AP in the scan window
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304095 *and the rssi icon of the wireless networks in sync
Jeff Johnson295189b2012-06-20 16:38:30 -07004096 * */
4097 if (( eConnectionState_Associated ==
4098 pAdapter->sessionCtx.station.conn_info.connState ) &&
4099 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
4100 pAdapter->sessionCtx.station.conn_info.bssId,
4101 WNI_CFG_BSSID_LEN)))
4102 {
4103 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
4104 rssi = (pAdapter->rssi * 100);
4105 }
4106 else
4107 {
4108 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
4109 }
4110
4111 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
4112 frame_len, rssi, GFP_KERNEL);
4113 kfree(mgmt);
4114 return bss_status;
4115}
4116
4117/*
4118 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
4119 * This function is used to update the BSS data base of CFG8011
4120 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304121struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07004122 tCsrRoamInfo *pRoamInfo
4123 )
4124{
4125 tCsrRoamConnectedProfile roamProfile;
4126 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4127 struct cfg80211_bss *bss = NULL;
4128
4129 ENTER();
4130
4131 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
4132 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
4133
4134 if (NULL != roamProfile.pBssDesc)
4135 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304136 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07004137 &roamProfile);
4138
4139 if (NULL == bss)
4140 {
4141 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
4142 __func__);
4143 }
4144
4145 sme_RoamFreeConnectProfile(hHal, &roamProfile);
4146 }
4147 else
4148 {
4149 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
4150 __func__);
4151 }
4152 return bss;
4153}
4154
4155/*
4156 * FUNCTION: wlan_hdd_cfg80211_update_bss
4157 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304158static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
4159 hdd_adapter_t *pAdapter
Jeff Johnson295189b2012-06-20 16:38:30 -07004160 )
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304161{
Jeff Johnson295189b2012-06-20 16:38:30 -07004162 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4163 tCsrScanResultInfo *pScanResult;
4164 eHalStatus status = 0;
4165 tScanResultHandle pResult;
4166 struct cfg80211_bss *bss_status = NULL;
4167
4168 ENTER();
4169
4170 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4171 {
4172 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
4173 return -EAGAIN;
4174 }
4175
4176 /*
4177 * start getting scan results and populate cgf80211 BSS database
4178 */
4179 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
4180
4181 /* no scan results */
4182 if (NULL == pResult)
4183 {
4184 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
4185 return status;
4186 }
4187
4188 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
4189
4190 while (pScanResult)
4191 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304192 /*
4193 * cfg80211_inform_bss() is not updating ie field of bss entry, if
4194 * entry already exists in bss data base of cfg80211 for that
4195 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
4196 * bss entry instead of cfg80211_inform_bss, But this call expects
4197 * mgmt packet as input. As of now there is no possibility to get
4198 * the mgmt(probe response) frame from PE, converting bss_desc to
Jeff Johnson295189b2012-06-20 16:38:30 -07004199 * ieee80211_mgmt(probe response) and passing to c
4200 * fg80211_inform_bss_frame.
4201 * */
4202
4203 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
4204 &pScanResult->BssDescriptor);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304205
Jeff Johnson295189b2012-06-20 16:38:30 -07004206
4207 if (NULL == bss_status)
4208 {
4209 hddLog(VOS_TRACE_LEVEL_INFO,
4210 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
4211 }
4212 else
4213 {
Yue Maf49ba872013-08-19 12:04:25 -07004214 cfg80211_put_bss(
4215#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
4216 wiphy,
4217#endif
4218 bss_status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004219 }
4220
4221 pScanResult = sme_ScanResultGetNext(hHal, pResult);
4222 }
4223
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304224 sme_ScanResultPurge(hHal, pResult);
Jeff Johnson295189b2012-06-20 16:38:30 -07004225
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304226 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004227}
4228
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004229void
4230hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
4231{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304232 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004233 "%02X:%02X:%02X:%02X:%02X:%02X\n",
4234 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
4235 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004236} /****** end hddPrintMacAddr() ******/
4237
4238void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004239hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004240{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304241 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004242 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
4243 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
4244 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
4245 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004246} /****** end hddPrintPmkId() ******/
4247
4248//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
4249//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
4250
4251//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
4252//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
4253
4254#define dump_bssid(bssid) \
4255 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004256 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
4257 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
4258 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004259 }
4260
4261#define dump_pmkid(pMac, pmkid) \
4262 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004263 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
4264 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
4265 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004266 }
4267
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07004268#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004269/*
4270 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
4271 * This function is used to notify the supplicant of a new PMKSA candidate.
4272 */
4273int wlan_hdd_cfg80211_pmksa_candidate_notify(
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304274 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004275 int index, bool preauth )
4276{
Jeff Johnsone7245742012-09-05 17:12:55 -07004277#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004278 struct net_device *dev = pAdapter->dev;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004279 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004280
4281 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07004282 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004283
4284 if( NULL == pRoamInfo )
4285 {
4286 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
4287 return -EINVAL;
4288 }
4289
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004290 if (eANI_BOOLEAN_TRUE == hdd_is_okc_mode_enabled(pHddCtx))
4291 {
4292 dump_bssid(pRoamInfo->bssid);
4293 cfg80211_pmksa_candidate_notify(dev, index,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004294 pRoamInfo->bssid, preauth, GFP_KERNEL);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004295 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004296#endif /* FEATURE_WLAN_OKC */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304297 return 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004298}
4299#endif //FEATURE_WLAN_LFR
4300
Jeff Johnson295189b2012-06-20 16:38:30 -07004301/*
4302 * FUNCTION: hdd_cfg80211_scan_done_callback
4303 * scanning callback function, called after finishing scan
4304 *
4305 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304306static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
Jeff Johnson295189b2012-06-20 16:38:30 -07004307 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
4308{
4309 struct net_device *dev = (struct net_device *) pContext;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304310 //struct wireless_dev *wdev = dev->ieee80211_ptr;
Jeff Johnson295189b2012-06-20 16:38:30 -07004311 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004312 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4313 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004314 struct cfg80211_scan_request *req = NULL;
4315 int ret = 0;
4316
4317 ENTER();
4318
4319 hddLog(VOS_TRACE_LEVEL_INFO,
4320 "%s called with halHandle = %p, pContext = %p,"
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304321 "scanID = %d, returned status = %d\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07004322 __func__, halHandle, pContext, (int) scanId, (int) status);
4323
4324 //Block on scan req completion variable. Can't wait forever though.
4325 ret = wait_for_completion_interruptible_timeout(
4326 &pScanInfo->scan_req_completion_event,
4327 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
4328 if (!ret)
4329 {
4330 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004331 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004332 }
4333
4334 if(pScanInfo->mScanPending != VOS_TRUE)
4335 {
4336 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004337 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004338 }
4339
4340 /* Check the scanId */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304341 if (pScanInfo->scanId != scanId)
Jeff Johnson295189b2012-06-20 16:38:30 -07004342 {
4343 hddLog(VOS_TRACE_LEVEL_INFO,
4344 "%s called with mismatched scanId pScanInfo->scanId = %d "
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304345 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
Jeff Johnson295189b2012-06-20 16:38:30 -07004346 (int) scanId);
4347 }
4348
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304349 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07004350 pAdapter);
4351
4352 if (0 > ret)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304353 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004354
4355
4356 /* If any client wait scan result through WEXT
4357 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004358 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07004359 {
4360 /* The other scan request waiting for current scan finish
4361 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004362 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004363 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004364 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004365 }
4366 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004367 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004368 {
4369 struct net_device *dev = pAdapter->dev;
4370 union iwreq_data wrqu;
4371 int we_event;
4372 char *msg;
4373
4374 memset(&wrqu, '\0', sizeof(wrqu));
4375 we_event = SIOCGIWSCAN;
4376 msg = NULL;
4377 wireless_send_event(dev, we_event, &wrqu, msg);
4378 }
4379 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004380 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004381
4382 /* Get the Scan Req */
4383 req = pAdapter->request;
4384
4385 if (!req)
4386 {
4387 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004388 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07004389 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004390 }
4391
4392 /*
4393 * setting up 0, just in case.
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304394 */
Jeff Johnson295189b2012-06-20 16:38:30 -07004395 req->n_ssids = 0;
4396 req->n_channels = 0;
4397 req->ie = 0;
4398
Jeff Johnson295189b2012-06-20 16:38:30 -07004399 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004400 /* Scan is no longer pending */
4401 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004402
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07004403 /*
4404 * cfg80211_scan_done informing NL80211 about completion
4405 * of scanning
4406 */
4407 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004408 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004409
Jeff Johnsone7245742012-09-05 17:12:55 -07004410allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004411 /* release the wake lock at the end of the scan*/
4412 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004413
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004414 /* Acquire wakelock to handle the case where APP's tries to suspend
4415 * immediatly after the driver gets connect request(i.e after scan)
4416 * from supplicant, this result in app's is suspending and not able
4417 * to process the connect request to AP */
Amar Singhal6144c002013-05-03 16:11:42 -07004418 hdd_allow_suspend_timeout(1000);
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004419
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004420#ifdef FEATURE_WLAN_TDLS
4421 wlan_hdd_tdls_scan_done_callback(pAdapter);
4422#endif
4423
Jeff Johnson295189b2012-06-20 16:38:30 -07004424 EXIT();
4425 return 0;
4426}
4427
4428/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004429 * FUNCTION: hdd_isScanAllowed
4430 * Go through each adapter and check if scan allowed
4431 *
4432 */
4433v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
4434{
4435 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4436 hdd_station_ctx_t *pHddStaCtx = NULL;
4437 hdd_adapter_t *pAdapter = NULL;
4438 VOS_STATUS status = 0;
4439 v_U8_t staId = 0;
4440 v_U8_t *staMac = NULL;
4441
4442 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4443
4444 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4445 {
4446 pAdapter = pAdapterNode->pAdapter;
4447
4448 if( pAdapter )
4449 {
4450 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304451 "%s: Adapter with device mode %d exists",
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004452 __func__, pAdapter->device_mode);
4453 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4454 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4455 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
4456 {
4457 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4458 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
4459 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
4460 {
4461 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
4462 hddLog(VOS_TRACE_LEVEL_ERROR,
4463 "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the "
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304464 "middle of WPS/EAPOL exchange.", __func__,
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004465 staMac[0], staMac[1], staMac[2],
4466 staMac[3], staMac[4], staMac[5]);
4467 return VOS_FALSE;
4468 }
4469 }
4470 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
4471 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
4472 {
4473 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
4474 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304475 if ((pAdapter->aStaInfo[staId].isUsed) &&
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004476 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
4477 {
4478 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
4479
4480 hddLog(VOS_TRACE_LEVEL_ERROR,
4481 "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the "
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304482 "middle of WPS/EAPOL exchange.", __func__,
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004483 staMac[0], staMac[1], staMac[2],
4484 staMac[3], staMac[4], staMac[5]);
4485 return VOS_FALSE;
4486 }
4487 }
4488 }
4489 }
4490 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4491 pAdapterNode = pNext;
4492 }
4493 hddLog(VOS_TRACE_LEVEL_INFO,
4494 "%s: Scan allowed", __func__);
4495 return VOS_TRUE;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304496}
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004497
4498/*
Jeff Johnson295189b2012-06-20 16:38:30 -07004499 * FUNCTION: wlan_hdd_cfg80211_scan
4500 * this scan respond to scan trigger and update cfg80211 scan database
4501 * later, scan dump command can be used to recieve scan results
4502 */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08004503int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
4504#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4505 struct net_device *dev,
4506#endif
4507 struct cfg80211_scan_request *request)
4508{
4509#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4510 struct net_device *dev = request->wdev->netdev;
4511#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304512 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07004513 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4514 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304515 hdd_config_t *cfg_param = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004516 tCsrScanRequest scanRequest;
4517 tANI_U8 *channelList = NULL, i;
4518 v_U32_t scanId = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304519 int status;
4520 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004521 v_U8_t* pP2pIe = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004522
4523 ENTER();
4524
4525 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4526 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004527
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304528 status = wlan_hdd_validate_context(pHddCtx);
4529
4530 if (0 != status)
4531 {
4532 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4533 "%s: HDD context is not valid", __func__);
4534 return status;
4535 }
4536
4537 cfg_param = pHddCtx->cfg_ini;
4538 pScanInfo = &pHddCtx->scan_info;
4539
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004540 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004541 (eConnectionState_Connecting ==
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004542 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004543 {
4544 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004545 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
4546 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004547 return -EBUSY;
4548 }
4549
Jeff Johnson295189b2012-06-20 16:38:30 -07004550#ifdef WLAN_BTAMP_FEATURE
4551 //Scan not supported when AMP traffic is on.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004552 if (VOS_TRUE == WLANBAP_AmpSessionOn())
Jeff Johnson295189b2012-06-20 16:38:30 -07004553 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004554 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004555 "%s: No scanning when AMP is on", __func__);
4556 return -EOPNOTSUPP;
4557 }
4558#endif
4559 //Scan on any other interface is not supported.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004560 if (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07004561 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004562 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004563 "%s: Not scanning on device_mode = %d",
4564 __func__, pAdapter->device_mode);
4565 return -EOPNOTSUPP;
4566 }
4567
4568 if (TRUE == pScanInfo->mScanPending)
4569 {
4570 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004571 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07004572 }
4573
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304574 //Don't Allow Scan and return busy if Remain On
Jeff Johnson32d95a32012-09-10 13:15:23 -07004575 //Channel and action frame is pending
4576 //Otherwise Cancel Remain On Channel and allow Scan
4577 //If no action frame pending
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004578 if (0 != wlan_hdd_check_remain_on_channel(pAdapter))
Jeff Johnson32d95a32012-09-10 13:15:23 -07004579 {
4580 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
4581 return -EBUSY;
4582 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004583#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004584 /* if tdls disagree scan right now, return immediately.
4585 tdls will schedule the scan when scan is allowed. (return SUCCESS)
4586 or will reject the scan if any TDLS is in progress. (return -EBUSY)
4587 */
4588 status = wlan_hdd_tdls_scan_callback (pAdapter,
4589 wiphy,
4590#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4591 dev,
Gopichand Nakkalac3c42b92013-03-20 19:42:34 -07004592#endif
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004593 request);
4594 if(status <= 0)
4595 {
4596 hddLog(VOS_TRACE_LEVEL_INFO, "%s: TDLS Pending %d", __func__, status);
4597 return status;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004598 }
4599#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07004600
Jeff Johnson295189b2012-06-20 16:38:30 -07004601 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
4602 {
4603 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08004604 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004605 return -EAGAIN;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304606 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004607 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
4608 {
4609 hddLog(VOS_TRACE_LEVEL_WARN,
4610 "%s: MAX TM Level Scan not allowed", __func__);
4611 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304612 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07004613 }
4614 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4615
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004616 /* Check if scan is allowed at this point of time.
4617 */
4618 if (!hdd_isScanAllowed(pHddCtx))
4619 {
4620 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
4621 return -EBUSY;
4622 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304623
Jeff Johnson295189b2012-06-20 16:38:30 -07004624 vos_mem_zero( &scanRequest, sizeof(scanRequest));
4625
4626 if (NULL != request)
4627 {
4628 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304629 (int)request->n_ssids);
Jeff Johnson295189b2012-06-20 16:38:30 -07004630
4631 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
4632 * Becasue of this, driver is assuming that this is not wildcard scan and so
4633 * is not aging out the scan results.
4634 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07004635 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07004636 {
4637 request->n_ssids = 0;
4638 }
4639
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004640 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07004641 {
4642 tCsrSSIDInfo *SsidInfo;
4643 int j;
4644 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
4645 /* Allocate num_ssid tCsrSSIDInfo structure */
4646 SsidInfo = scanRequest.SSIDs.SSIDList =
4647 ( tCsrSSIDInfo *)vos_mem_malloc(
4648 request->n_ssids*sizeof(tCsrSSIDInfo));
4649
4650 if(NULL == scanRequest.SSIDs.SSIDList)
4651 {
4652 hddLog(VOS_TRACE_LEVEL_ERROR,
4653 "memory alloc failed SSIDInfo buffer");
4654 return -ENOMEM;
4655 }
4656
4657 /* copy all the ssid's and their length */
4658 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
4659 {
4660 /* get the ssid length */
4661 SsidInfo->SSID.length = request->ssids[j].ssid_len;
4662 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
4663 SsidInfo->SSID.length);
4664 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
4665 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
4666 j, SsidInfo->SSID.ssId);
4667 }
4668 /* set the scan type to active */
4669 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4670 }
4671 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4672 {
4673 /* set the scan type to active */
4674 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4675 }
4676 else
4677 {
4678 /*Set the scan type to default type, in this case it is ACTIVE*/
4679 scanRequest.scanType = pScanInfo->scan_mode;
4680 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304681 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
Jeff Johnson295189b2012-06-20 16:38:30 -07004682 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4683 }
4684 else
4685 {
4686 /* set the scan type to active */
4687 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4688 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4689
4690 /* set min and max channel time to zero */
4691 scanRequest.minChnTime = 0;
4692 scanRequest.maxChnTime = 0;
4693 }
4694
4695 /* set BSSType to default type */
4696 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4697
4698 /*TODO: scan the requested channels only*/
4699
4700 /*Right now scanning all the channels */
4701 if( request )
4702 {
4703 if( request->n_channels )
4704 {
4705 channelList = vos_mem_malloc( request->n_channels );
4706 if( NULL == channelList )
4707 {
4708 status = -ENOMEM;
4709 goto free_mem;
4710 }
4711
4712 for( i = 0 ; i < request->n_channels ; i++ )
4713 channelList[i] = request->channels[i]->hw_value;
4714 }
4715
4716 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4717 scanRequest.ChannelInfo.ChannelList = channelList;
4718
4719 /* set requestType to full scan */
4720 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304721
4722 /* Flush the scan results(only p2p beacons) for STA scan and P2P
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004723 * search (Flush on both full scan and social scan but not on single
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304724 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004725 */
4726
4727 /* Supplicant does single channel scan after 8-way handshake
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304728 * and in that case driver shoudnt flush scan results. If
4729 * driver flushes the scan results here and unfortunately if
4730 * the AP doesnt respond to our probe req then association
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004731 * fails which is not desired
4732 */
4733
4734 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4735 {
4736 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4737 pAdapter->sessionId );
4738 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004739
4740 if( request->ie_len )
4741 {
4742 /* save this for future association (join requires this) */
4743 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4744 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4745 pScanInfo->scanAddIE.length = request->ie_len;
4746
4747 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004748 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4749 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004750 )
4751 {
4752 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4753 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4754 }
4755
4756 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4757 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4758
Jeff Johnson295189b2012-06-20 16:38:30 -07004759 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4760 request->ie_len);
4761 if (pP2pIe != NULL)
4762 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004763#ifdef WLAN_FEATURE_P2P_DEBUG
4764 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4765 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4766 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4767 {
4768 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4769 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4770 "Go nego completed to Connection is started");
4771 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4772 "for 8way Handshake");
4773 }
4774 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4775 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4776 {
4777 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4778 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4779 "Disconnected state to Connection is started");
4780 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4781 "for 4way Handshake");
4782 }
4783#endif
4784
Jeff Johnsone7245742012-09-05 17:12:55 -07004785 /* no_cck will be set during p2p find to disable 11b rates */
4786 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004787 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004788 hddLog(VOS_TRACE_LEVEL_INFO,
4789 "%s: This is a P2P Search", __func__);
4790 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004791
Jeff Johnsone7245742012-09-05 17:12:55 -07004792 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4793 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004794 /* set requestType to P2P Discovery */
4795 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004796 }
4797
4798 /*
4799 Skip Dfs Channel in case of P2P Search
4800 if it is set in ini file
4801 */
4802 if(cfg_param->skipDfsChnlInP2pSearch)
4803 {
4804 scanRequest.skipDfsChnlInP2pSearch = 1;
4805 }
4806 else
4807 {
4808 scanRequest.skipDfsChnlInP2pSearch = 0;
4809 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004810
Jeff Johnson295189b2012-06-20 16:38:30 -07004811 }
4812 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004813 }
4814 }
4815
4816 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4817
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004818 /* acquire the wakelock to avoid the apps suspend during the scan. To
4819 * address the following issues.
4820 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4821 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4822 * for long time, this result in apps running at full power for long time.
4823 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4824 * be stuck in full power because of resume BMPS
4825 */
4826 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004827
4828 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004829 pAdapter->sessionId, &scanRequest, &scanId,
4830 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004831
Jeff Johnson295189b2012-06-20 16:38:30 -07004832 if (eHAL_STATUS_SUCCESS != status)
4833 {
4834 hddLog(VOS_TRACE_LEVEL_ERROR,
4835 "%s: sme_ScanRequest returned error %d", __func__, status);
4836 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004837 if(eHAL_STATUS_RESOURCES == status)
4838 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004839 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 -07004840 status = -EBUSY;
4841 } else {
4842 status = -EIO;
4843 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004844 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004845 goto free_mem;
4846 }
4847
4848 pScanInfo->mScanPending = TRUE;
4849 pAdapter->request = request;
4850 pScanInfo->scanId = scanId;
4851
4852 complete(&pScanInfo->scan_req_completion_event);
4853
4854free_mem:
4855 if( scanRequest.SSIDs.SSIDList )
4856 {
4857 vos_mem_free(scanRequest.SSIDs.SSIDList);
4858 }
4859
4860 if( channelList )
4861 vos_mem_free( channelList );
4862
4863 EXIT();
4864
4865 return status;
4866}
4867
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07004868
4869void hdd_select_cbmode( hdd_adapter_t *pAdapter,v_U8_t operationChannel)
4870{
4871 v_U8_t iniDot11Mode =
4872 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->dot11Mode;
4873 eHddDot11Mode hddDot11Mode = iniDot11Mode;
4874
4875 switch ( iniDot11Mode )
4876 {
4877 case eHDD_DOT11_MODE_AUTO:
4878 case eHDD_DOT11_MODE_11ac:
4879 case eHDD_DOT11_MODE_11ac_ONLY:
4880#ifdef WLAN_FEATURE_11AC
4881 hddDot11Mode = eHDD_DOT11_MODE_11ac;
4882#else
4883 hddDot11Mode = eHDD_DOT11_MODE_11n;
4884#endif
4885 break;
4886 case eHDD_DOT11_MODE_11n:
4887 case eHDD_DOT11_MODE_11n_ONLY:
4888 hddDot11Mode = eHDD_DOT11_MODE_11n;
4889 break;
4890 default:
4891 hddDot11Mode = iniDot11Mode;
4892 break;
4893 }
4894 /* This call decides required channel bonding mode */
4895 sme_SelectCBMode((WLAN_HDD_GET_CTX(pAdapter)->hHal),
4896 hdd_cfg_xlate_to_csr_phy_mode(hddDot11Mode),
4897 operationChannel);
4898}
4899
Jeff Johnson295189b2012-06-20 16:38:30 -07004900/*
4901 * FUNCTION: wlan_hdd_cfg80211_connect_start
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304902 * This function is used to start the association process
Jeff Johnson295189b2012-06-20 16:38:30 -07004903 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304904int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004905 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004906{
4907 int status = 0;
4908 hdd_wext_state_t *pWextState;
4909 v_U32_t roamId;
4910 tCsrRoamProfile *pRoamProfile;
4911 eMib_dot11DesiredBssType connectedBssType;
4912 eCsrAuthType RSNAuthType;
4913
4914 ENTER();
4915
4916 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304917
Jeff Johnson295189b2012-06-20 16:38:30 -07004918 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4919 {
4920 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4921 return -EINVAL;
4922 }
4923
4924 pRoamProfile = &pWextState->roamProfile;
4925
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304926 if (pRoamProfile)
Jeff Johnson295189b2012-06-20 16:38:30 -07004927 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004928 int ret = 0;
4929 hdd_station_ctx_t *pHddStaCtx;
4930 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4931 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4932
4933 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4934 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4935 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004936 {
4937 /* Issue disconnect to CSR */
4938 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304939 if( eHAL_STATUS_SUCCESS ==
Jeff Johnson295189b2012-06-20 16:38:30 -07004940 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4941 pAdapter->sessionId,
4942 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4943 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004944 ret = wait_for_completion_interruptible_timeout(
4945 &pAdapter->disconnect_comp_var,
4946 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4947 if (0 == ret)
4948 {
4949 VOS_ASSERT(0);
4950 }
4951 }
4952 }
4953 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4954 {
4955 ret = wait_for_completion_interruptible_timeout(
4956 &pAdapter->disconnect_comp_var,
4957 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4958 if (0 == ret)
4959 {
4960 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004961 }
4962 }
4963
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304964 if (HDD_WMM_USER_MODE_NO_QOS ==
Jeff Johnson295189b2012-06-20 16:38:30 -07004965 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4966 {
4967 /*QoS not enabled in cfg file*/
4968 pRoamProfile->uapsd_mask = 0;
4969 }
4970 else
4971 {
4972 /*QoS enabled, update uapsd mask from cfg file*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304973 pRoamProfile->uapsd_mask =
Jeff Johnson295189b2012-06-20 16:38:30 -07004974 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4975 }
4976
4977 pRoamProfile->SSIDs.numOfSSIDs = 1;
4978 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4979 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304980 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Jeff Johnson295189b2012-06-20 16:38:30 -07004981 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4982 ssid, ssid_len);
4983
4984 if (bssid)
4985 {
4986 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4987 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4988 WNI_CFG_BSSID_LEN);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304989 /* Save BSSID in seperate variable as well, as RoamProfile
4990 BSSID is getting zeroed out in the association process. And in
Jeff Johnson295189b2012-06-20 16:38:30 -07004991 case of join failure we should send valid BSSID to supplicant
4992 */
4993 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4994 WNI_CFG_BSSID_LEN);
4995 }
Dhanashri Atre51981c62013-06-13 11:47:57 -07004996 else
4997 {
4998 vos_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),WNI_CFG_BSSID_LEN);
4999 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005000
5001 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
5002 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305003 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005004 /*set gen ie*/
5005 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
5006 /*set auth*/
5007 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
5008 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005009#ifdef FEATURE_WLAN_WAPI
5010 if (pAdapter->wapi_info.nWapiMode)
5011 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005012 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005013 switch (pAdapter->wapi_info.wapiAuthMode)
5014 {
5015 case WAPI_AUTH_MODE_PSK:
5016 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005017 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07005018 pAdapter->wapi_info.wapiAuthMode);
5019 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
5020 break;
5021 }
5022 case WAPI_AUTH_MODE_CERT:
5023 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005024 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07005025 pAdapter->wapi_info.wapiAuthMode);
5026 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
5027 break;
5028 }
5029 } // End of switch
5030 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
5031 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
5032 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005033 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005034 pRoamProfile->AuthType.numEntries = 1;
5035 pRoamProfile->EncryptionType.numEntries = 1;
5036 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
5037 pRoamProfile->mcEncryptionType.numEntries = 1;
5038 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
5039 }
5040 }
5041#endif /* FEATURE_WLAN_WAPI */
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05305042#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05305043 /* Initializing gtkOffloadReqParams */
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05305044 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5045 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
5046 {
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05305047 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
5048 sizeof (tSirGtkOffloadParams));
5049 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05305050 }
5051#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005052 pRoamProfile->csrPersona = pAdapter->device_mode;
5053
Jeff Johnson32d95a32012-09-10 13:15:23 -07005054 if( operatingChannel )
5055 {
5056 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
5057 pRoamProfile->ChannelInfo.numOfChannels = 1;
5058 }
Chet Lanctot186b5732013-03-18 10:26:30 -07005059 else
5060 {
5061 pRoamProfile->ChannelInfo.ChannelList = NULL;
5062 pRoamProfile->ChannelInfo.numOfChannels = 0;
5063 }
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07005064 if ( (WLAN_HDD_IBSS == pAdapter->device_mode) && operatingChannel)
5065 {
5066 hdd_select_cbmode(pAdapter,operatingChannel);
5067 }
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005068 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
5069 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305070 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005071 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08005072 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
5073 */
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305074 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
5075 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08005076 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
5077 eConnectionState_Connecting);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305078
5079 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07005080 pAdapter->sessionId, pRoamProfile, &roamId);
5081
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305082 if ((eHAL_STATUS_SUCCESS != status) &&
5083 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
5084 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05305085
5086 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005087 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
5088 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
5089 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05305090 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005091 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05305092 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08005093
5094 pRoamProfile->ChannelInfo.ChannelList = NULL;
5095 pRoamProfile->ChannelInfo.numOfChannels = 0;
5096
Jeff Johnson295189b2012-06-20 16:38:30 -07005097 }
5098 else
5099 {
5100 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
5101 return -EINVAL;
5102 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08005103 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005104 return status;
5105}
5106
5107/*
5108 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
5109 * This function is used to set the authentication type (OPEN/SHARED).
5110 *
5111 */
5112static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
5113 enum nl80211_auth_type auth_type)
5114{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305115 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005116 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5117
5118 ENTER();
5119
5120 /*set authentication type*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305121 switch (auth_type)
Jeff Johnson295189b2012-06-20 16:38:30 -07005122 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005123 case NL80211_AUTHTYPE_AUTOMATIC:
Gopichand Nakkala29149562013-05-10 21:43:41 +05305124 hddLog(VOS_TRACE_LEVEL_INFO,
5125 "%s: set authentication type to AUTOSWITCH", __func__);
5126 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
5127 break;
5128
5129 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07005130#ifdef WLAN_FEATURE_VOWIFI_11R
5131 case NL80211_AUTHTYPE_FT:
5132#endif /* WLAN_FEATURE_VOWIFI_11R */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305133 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07005134 "%s: set authentication type to OPEN", __func__);
5135 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5136 break;
5137
5138 case NL80211_AUTHTYPE_SHARED_KEY:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305139 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07005140 "%s: set authentication type to SHARED", __func__);
5141 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
5142 break;
5143#ifdef FEATURE_WLAN_CCX
5144 case NL80211_AUTHTYPE_NETWORK_EAP:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305145 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07005146 "%s: set authentication type to CCKM WPA", __func__);
5147 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
5148 break;
5149#endif
5150
5151
5152 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305153 hddLog(VOS_TRACE_LEVEL_ERROR,
5154 "%s: Unsupported authentication type %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07005155 auth_type);
5156 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
5157 return -EINVAL;
5158 }
5159
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305160 pWextState->roamProfile.AuthType.authType[0] =
Jeff Johnson295189b2012-06-20 16:38:30 -07005161 pHddStaCtx->conn_info.authType;
5162 return 0;
5163}
5164
5165/*
5166 * FUNCTION: wlan_hdd_set_akm_suite
5167 * This function is used to set the key mgmt type(PSK/8021x).
5168 *
5169 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305170static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07005171 u32 key_mgmt
5172 )
5173{
5174 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5175 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305176
Jeff Johnson295189b2012-06-20 16:38:30 -07005177 /*set key mgmt type*/
5178 switch(key_mgmt)
5179 {
5180 case WLAN_AKM_SUITE_PSK:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05305181#ifdef WLAN_FEATURE_VOWIFI_11R
5182 case WLAN_AKM_SUITE_FT_PSK:
5183#endif
5184 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
Jeff Johnson295189b2012-06-20 16:38:30 -07005185 __func__);
5186 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
5187 break;
5188
5189 case WLAN_AKM_SUITE_8021X:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05305190#ifdef WLAN_FEATURE_VOWIFI_11R
5191 case WLAN_AKM_SUITE_FT_8021X:
5192#endif
5193 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
Jeff Johnson295189b2012-06-20 16:38:30 -07005194 __func__);
5195 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
5196 break;
5197#ifdef FEATURE_WLAN_CCX
5198#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
5199#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
5200 case WLAN_AKM_SUITE_CCKM:
5201 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
5202 __func__);
5203 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
5204 break;
5205#endif
5206
5207 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305208 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005209 __func__, key_mgmt);
5210 return -EINVAL;
5211
5212 }
5213 return 0;
5214}
5215
5216/*
5217 * FUNCTION: wlan_hdd_cfg80211_set_cipher
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305218 * This function is used to set the encryption type
Jeff Johnson295189b2012-06-20 16:38:30 -07005219 * (NONE/WEP40/WEP104/TKIP/CCMP).
5220 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305221static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
5222 u32 cipher,
Jeff Johnson295189b2012-06-20 16:38:30 -07005223 bool ucast
5224 )
5225{
5226 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305227 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005228 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5229
5230 ENTER();
5231
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305232 if (!cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07005233 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305234 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
Jeff Johnson295189b2012-06-20 16:38:30 -07005235 __func__, cipher);
5236 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5237 }
5238 else
5239 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305240
Jeff Johnson295189b2012-06-20 16:38:30 -07005241 /*set encryption method*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305242 switch (cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07005243 {
5244 case IW_AUTH_CIPHER_NONE:
5245 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5246 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305247
Jeff Johnson295189b2012-06-20 16:38:30 -07005248 case WLAN_CIPHER_SUITE_WEP40:
Gopichand Nakkala29149562013-05-10 21:43:41 +05305249 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
Jeff Johnson295189b2012-06-20 16:38:30 -07005250 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305251
Jeff Johnson295189b2012-06-20 16:38:30 -07005252 case WLAN_CIPHER_SUITE_WEP104:
Gopichand Nakkala29149562013-05-10 21:43:41 +05305253 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
Jeff Johnson295189b2012-06-20 16:38:30 -07005254 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305255
Jeff Johnson295189b2012-06-20 16:38:30 -07005256 case WLAN_CIPHER_SUITE_TKIP:
5257 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5258 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305259
Jeff Johnson295189b2012-06-20 16:38:30 -07005260 case WLAN_CIPHER_SUITE_CCMP:
5261 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5262 break;
5263#ifdef FEATURE_WLAN_WAPI
5264 case WLAN_CIPHER_SUITE_SMS4:
5265 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
5266 break;
5267#endif
5268
5269#ifdef FEATURE_WLAN_CCX
5270 case WLAN_CIPHER_SUITE_KRK:
5271 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
5272 break;
5273#endif
5274 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305275 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005276 __func__, cipher);
5277 return -EOPNOTSUPP;
5278 }
5279 }
5280
5281 if (ucast)
5282 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305283 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005284 __func__, encryptionType);
5285 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5286 pWextState->roamProfile.EncryptionType.numEntries = 1;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305287 pWextState->roamProfile.EncryptionType.encryptionType[0] =
Jeff Johnson295189b2012-06-20 16:38:30 -07005288 encryptionType;
5289 }
5290 else
5291 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305292 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005293 __func__, encryptionType);
5294 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
5295 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
5296 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
5297 }
5298
5299 return 0;
5300}
5301
5302
5303/*
5304 * FUNCTION: wlan_hdd_cfg80211_set_ie
5305 * This function is used to parse WPA/RSN IE's.
5306 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305307int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
5308 u8 *ie,
Jeff Johnson295189b2012-06-20 16:38:30 -07005309 size_t ie_len
5310 )
5311{
5312 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5313 u8 *genie = ie;
5314 v_U16_t remLen = ie_len;
5315#ifdef FEATURE_WLAN_WAPI
5316 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
5317 u16 *tmp;
5318 v_U16_t akmsuiteCount;
5319 int *akmlist;
5320#endif
5321 ENTER();
5322
5323 /* clear previous assocAddIE */
5324 pWextState->assocAddIE.length = 0;
5325 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
5326
5327 while (remLen >= 2)
5328 {
5329 v_U16_t eLen = 0;
5330 v_U8_t elementId;
5331 elementId = *genie++;
5332 eLen = *genie++;
5333 remLen -= 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305334
5335 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07005336 __func__, elementId, eLen);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305337
5338 switch ( elementId )
Jeff Johnson295189b2012-06-20 16:38:30 -07005339 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305340 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005341 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 -07005342 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305343 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005344 "%s: Invalid WPA IE", __func__);
5345 return -EINVAL;
5346 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305347 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
Jeff Johnson295189b2012-06-20 16:38:30 -07005348 {
5349 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305350 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
Jeff Johnson295189b2012-06-20 16:38:30 -07005351 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305352
Jeff Johnson295189b2012-06-20 16:38:30 -07005353 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5354 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005355 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
5356 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005357 VOS_ASSERT(0);
5358 return -ENOMEM;
5359 }
5360 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5361 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5362 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305363
Jeff Johnson295189b2012-06-20 16:38:30 -07005364 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
5365 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5366 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5367 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305368 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
5369 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005370 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
5371 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5372 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
5373 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
5374 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
5375 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305376 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
5377 P2P_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07005378 /*Consider P2P IE, only for P2P Client */
5379 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5380 {
5381 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305382 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
Jeff Johnson295189b2012-06-20 16:38:30 -07005383 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305384
Jeff Johnson295189b2012-06-20 16:38:30 -07005385 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5386 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005387 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5388 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005389 VOS_ASSERT(0);
5390 return -ENOMEM;
5391 }
5392 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5393 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5394 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305395
Jeff Johnson295189b2012-06-20 16:38:30 -07005396 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5397 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5398 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005399#ifdef WLAN_FEATURE_WFD
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305400 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
5401 WFD_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07005402 /*Consider WFD IE, only for P2P Client */
5403 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5404 {
5405 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305406 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
Jeff Johnson295189b2012-06-20 16:38:30 -07005407 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305408
Jeff Johnson295189b2012-06-20 16:38:30 -07005409 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5410 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005411 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5412 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005413 VOS_ASSERT(0);
5414 return -ENOMEM;
5415 }
5416 // WFD IE is saved to Additional IE ; it should be accumulated to handle
5417 // WPS IE + P2P IE + WFD IE
5418 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5419 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305420
Jeff Johnson295189b2012-06-20 16:38:30 -07005421 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5422 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5423 }
5424#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005425 /* Appending HS 2.0 Indication Element in Assiciation Request */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305426 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005427 HS20_OUI_TYPE_SIZE)) )
5428 {
5429 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305430 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005431 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005432
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005433 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5434 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005435 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5436 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005437 VOS_ASSERT(0);
5438 return -ENOMEM;
5439 }
5440 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5441 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005442
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005443 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5444 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5445 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005446
Jeff Johnson295189b2012-06-20 16:38:30 -07005447 break;
5448 case DOT11F_EID_RSN:
5449 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
5450 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5451 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
5452 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
5453 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
5454 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005455 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
5456 case DOT11F_EID_EXTCAP:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305457 {
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005458 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305459 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005460 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305461
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005462 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5463 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005464 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5465 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005466 VOS_ASSERT(0);
5467 return -ENOMEM;
5468 }
5469 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5470 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305471
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005472 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5473 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5474 break;
5475 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005476#ifdef FEATURE_WLAN_WAPI
5477 case WLAN_EID_WAPI:
5478 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
5479 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
5480 pAdapter->wapi_info.nWapiMode);
5481 tmp = (u16 *)ie;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305482 tmp = tmp + 2; // Skip element Id and Len, Version
Jeff Johnson295189b2012-06-20 16:38:30 -07005483 akmsuiteCount = WPA_GET_LE16(tmp);
5484 tmp = tmp + 1;
5485 akmlist = (int *)(tmp);
5486 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
5487 {
5488 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
5489 }
5490 else
5491 {
5492 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
5493 VOS_ASSERT(0);
5494 return -EINVAL;
5495 }
5496
5497 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
5498 {
5499 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005500 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005501 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305502 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005503 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305504 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005505 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005506 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005507 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
5508 }
5509 break;
5510#endif
5511 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305512 hddLog (VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005513 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005514 /* when Unknown IE is received we should break and continue
5515 * to the next IE in the buffer instead we were returning
5516 * so changing this to break */
5517 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005518 }
5519 genie += eLen;
5520 remLen -= eLen;
5521 }
5522 EXIT();
5523 return 0;
5524}
5525
5526/*
Gopichand Nakkala18f0c262013-05-07 23:25:08 +05305527 * FUNCTION: hdd_isWPAIEPresent
5528 * Parse the received IE to find the WPA IE
5529 *
5530 */
5531static bool hdd_isWPAIEPresent(u8 *ie, u8 ie_len)
5532{
5533 v_U8_t eLen = 0;
5534 v_U16_t remLen = ie_len;
5535 v_U8_t elementId = 0;
5536
5537 while (remLen >= 2)
5538 {
5539 elementId = *ie++;
5540 eLen = *ie++;
5541 remLen -= 2;
5542 if (eLen > remLen)
5543 {
5544 hddLog(VOS_TRACE_LEVEL_ERROR,
5545 "%s: IE length is wrong %d", __func__, eLen);
5546 return FALSE;
5547 }
5548 if ((elementId == DOT11F_EID_WPA) && (remLen > 5))
5549 {
5550 /* OUI - 0x00 0X50 0XF2
5551 WPA Information Element - 0x01
5552 WPA version - 0x01*/
5553 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
5554 return TRUE;
5555 }
5556 ie += eLen;
5557 remLen -= eLen;
5558 }
5559 return FALSE;
5560}
5561
5562/*
Jeff Johnson295189b2012-06-20 16:38:30 -07005563 * FUNCTION: wlan_hdd_cfg80211_set_privacy
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305564 * This function is used to initialize the security
Jeff Johnson295189b2012-06-20 16:38:30 -07005565 * parameters during connect operation.
5566 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305567int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07005568 struct cfg80211_connect_params *req
5569 )
5570{
5571 int status = 0;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305572 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005573 ENTER();
5574
5575 /*set wpa version*/
5576 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5577
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305578 if (req->crypto.wpa_versions)
Jeff Johnson295189b2012-06-20 16:38:30 -07005579 {
Gopichand Nakkala781ded42013-06-28 12:10:45 +05305580 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
Jeff Johnson295189b2012-06-20 16:38:30 -07005581 {
5582 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5583 }
5584 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
5585 {
5586 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5587 }
5588 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305589
5590 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07005591 pWextState->wpaVersion);
5592
5593 /*set authentication type*/
5594 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
5595
5596 if (0 > status)
5597 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305598 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005599 "%s: failed to set authentication type ", __func__);
5600 return status;
5601 }
5602
5603 /*set key mgmt type*/
5604 if (req->crypto.n_akm_suites)
5605 {
5606 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
5607 if (0 > status)
5608 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305609 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
Jeff Johnson295189b2012-06-20 16:38:30 -07005610 __func__);
5611 return status;
5612 }
5613 }
5614
5615 /*set pairwise cipher type*/
5616 if (req->crypto.n_ciphers_pairwise)
5617 {
5618 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
5619 req->crypto.ciphers_pairwise[0], true);
5620 if (0 > status)
5621 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305622 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005623 "%s: failed to set unicast cipher type", __func__);
5624 return status;
5625 }
5626 }
5627 else
5628 {
5629 /*Reset previous cipher suite to none*/
5630 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
5631 if (0 > status)
5632 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305633 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005634 "%s: failed to set unicast cipher type", __func__);
5635 return status;
5636 }
5637 }
5638
5639 /*set group cipher type*/
5640 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
5641 false);
5642
5643 if (0 > status)
5644 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305645 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
Jeff Johnson295189b2012-06-20 16:38:30 -07005646 __func__);
5647 return status;
5648 }
5649
Chet Lanctot186b5732013-03-18 10:26:30 -07005650#ifdef WLAN_FEATURE_11W
5651 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
5652#endif
5653
Jeff Johnson295189b2012-06-20 16:38:30 -07005654 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
5655 if (req->ie_len)
5656 {
5657 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
5658 if ( 0 > status)
5659 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305660 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
Jeff Johnson295189b2012-06-20 16:38:30 -07005661 __func__);
5662 return status;
5663 }
5664 }
5665
5666 /*incase of WEP set default key information*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305667 if (req->key && req->key_len)
Jeff Johnson295189b2012-06-20 16:38:30 -07005668 {
5669 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
5670 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
5671 )
5672 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305673 if ( IW_AUTH_KEY_MGMT_802_1X
Jeff Johnson295189b2012-06-20 16:38:30 -07005674 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
5675 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305676 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
Jeff Johnson295189b2012-06-20 16:38:30 -07005677 __func__);
5678 return -EOPNOTSUPP;
5679 }
5680 else
5681 {
5682 u8 key_len = req->key_len;
5683 u8 key_idx = req->key_idx;
5684
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305685 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
Jeff Johnson295189b2012-06-20 16:38:30 -07005686 && (CSR_MAX_NUM_KEY > key_idx)
5687 )
5688 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305689 hddLog(VOS_TRACE_LEVEL_INFO,
5690 "%s: setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07005691 __func__, key_idx, key_len);
5692 vos_mem_copy(
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305693 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07005694 req->key, key_len);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305695 pWextState->roamProfile.Keys.KeyLength[key_idx] =
Jeff Johnson295189b2012-06-20 16:38:30 -07005696 (u8)key_len;
5697 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
5698 }
5699 }
5700 }
5701 }
5702
5703 return status;
5704}
5705
5706/*
5707 * FUNCTION: wlan_hdd_cfg80211_set_privacy
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305708 * This function is used to initialize the security
Jeff Johnson295189b2012-06-20 16:38:30 -07005709 * parameters during connect operation.
5710 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305711static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07005712 struct net_device *ndev,
5713 struct cfg80211_connect_params *req
5714 )
5715{
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305716 int status;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305717 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07005718 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
5719 hdd_context_t *pHddCtx = NULL;
5720
5721 ENTER();
5722
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305723 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07005724 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5725
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305726 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5727 status = wlan_hdd_validate_context(pHddCtx);
5728
5729 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07005730 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305731 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5732 "%s: HDD context is not valid", __func__);
5733 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07005734 }
5735
5736#ifdef WLAN_BTAMP_FEATURE
5737 //Infra connect not supported when AMP traffic is on.
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305738 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
Jeff Johnson295189b2012-06-20 16:38:30 -07005739 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305740 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005741 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005742 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07005743 }
5744#endif
5745 /*initialise security parameters*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305746 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
Jeff Johnson295189b2012-06-20 16:38:30 -07005747
5748 if ( 0 > status)
5749 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305750 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
Jeff Johnson295189b2012-06-20 16:38:30 -07005751 __func__);
5752 return status;
5753 }
5754
5755 //If Device Mode is Station Concurrent Sessions Exit BMps
Jeff Johnsona8a1a482012-12-12 16:49:33 -08005756 //P2P Mode will be taken care in Open/close adapter
Jeff Johnson295189b2012-06-20 16:38:30 -07005757 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
5758 (vos_concurrent_sessions_running()))
5759 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305760 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
Jeff Johnson295189b2012-06-20 16:38:30 -07005761 }
5762
Mohit Khanna765234a2012-09-11 15:08:35 -07005763 if ( req->channel )
5764 {
5765 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5766 req->ssid_len, req->bssid,
5767 req->channel->hw_value);
5768 }
5769 else
5770 {
5771 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305772 req->ssid_len, req->bssid, 0);
Mohit Khanna765234a2012-09-11 15:08:35 -07005773 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005774
5775 if (0 > status)
5776 {
5777 //ReEnable BMPS if disabled
5778 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5779 (NULL != pHddCtx))
5780 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305781 if (pHddCtx->hdd_wlan_suspended)
5782 {
5783 hdd_set_pwrparams(pHddCtx);
5784 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005785 //ReEnable Bmps and Imps back
5786 hdd_enable_bmps_imps(pHddCtx);
5787 }
5788
5789 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5790 return status;
5791 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305792 pHddCtx->isAmpAllowed = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005793 EXIT();
5794 return status;
5795}
5796
5797
5798/*
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05305799 * FUNCTION: wlan_hdd_disconnect
5800 * This function is used to issue a disconnect request to SME
5801 */
5802int wlan_hdd_disconnect( hdd_adapter_t *pAdapter, u16 reason )
5803{
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305804 int status;
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05305805 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305806 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5807
5808 status = wlan_hdd_validate_context(pHddCtx);
5809
5810 if (0 != status)
5811 {
5812 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5813 "%s: HDD context is not valid", __func__);
5814 return status;
5815 }
5816
5817 pHddCtx->isAmpAllowed = VOS_TRUE;
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05305818 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05305819 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305820
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05305821 /*issue disconnect*/
5822 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5823 pAdapter->sessionId, reason);
5824
5825 if ( 0 != status )
5826 {
5827 hddLog(VOS_TRACE_LEVEL_ERROR,
5828 "%s csrRoamDisconnect failure, returned %d \n",
5829 __func__, (int)status );
5830 return -EINVAL;
5831 }
5832 wait_for_completion_interruptible_timeout(
5833 &pAdapter->disconnect_comp_var,
5834 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5835 /*stop tx queues*/
5836 netif_tx_disable(pAdapter->dev);
5837 netif_carrier_off(pAdapter->dev);
5838 return status;
5839}
5840
5841
5842/*
Jeff Johnson295189b2012-06-20 16:38:30 -07005843 * FUNCTION: wlan_hdd_cfg80211_disconnect
5844 * This function is used to issue a disconnect request to SME
5845 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305846static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07005847 struct net_device *dev,
5848 u16 reason
5849 )
5850{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305851 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5852 tCsrRoamProfile *pRoamProfile =
Jeff Johnson295189b2012-06-20 16:38:30 -07005853 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305854 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07005855 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005856 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05305857#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005858 tANI_U8 staIdx;
5859#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305860
Jeff Johnson295189b2012-06-20 16:38:30 -07005861 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305862
5863 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07005864 __func__,pAdapter->device_mode);
5865
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305866 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5867 __func__, reason);
Jeff Johnson295189b2012-06-20 16:38:30 -07005868
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305869 status = wlan_hdd_validate_context(pHddCtx);
5870
5871 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07005872 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305873 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5874 "%s: HDD context is not valid", __func__);
5875 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07005876 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305877
Jeff Johnson295189b2012-06-20 16:38:30 -07005878 if (NULL != pRoamProfile)
5879 {
5880 /*issue disconnect request to SME, if station is in connected state*/
5881 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
5882 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305883 eCsrRoamDisconnectReason reasonCode =
Jeff Johnson295189b2012-06-20 16:38:30 -07005884 eCSR_DISCONNECT_REASON_UNSPECIFIED;
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05305885 hdd_scaninfo_t *pScanInfo;
Jeff Johnson295189b2012-06-20 16:38:30 -07005886 switch(reason)
5887 {
5888 case WLAN_REASON_MIC_FAILURE:
5889 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
5890 break;
5891
5892 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
5893 case WLAN_REASON_DISASSOC_AP_BUSY:
5894 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
5895 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
5896 break;
5897
5898 case WLAN_REASON_PREV_AUTH_NOT_VALID:
5899 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
5900 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
5901 break;
5902
5903 case WLAN_REASON_DEAUTH_LEAVING:
5904 default:
5905 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
5906 break;
5907 }
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05305908 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5909 pScanInfo = &pHddCtx->scan_info;
5910 if (pScanInfo->mScanPending)
5911 {
5912 hddLog(VOS_TRACE_LEVEL_INFO, "Disconnect is in progress, "
5913 "Aborting Scan");
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05305914 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05305915 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005916
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005917#ifdef FEATURE_WLAN_TDLS
5918 /* First clean up the tdls peers if any */
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005919 for (staIdx = 0 ; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005920 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005921 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId == pAdapter->sessionId) &&
5922 (pHddCtx->tdlsConnInfo[staIdx].staId))
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005923 {
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005924 uint8 *mac;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005925 mac = pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005926 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07005927 "%s: call sme_DeleteTdlsPeerSta staId %d sessionId %d " MAC_ADDRESS_STR,
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005928 __func__, pHddCtx->tdlsConnInfo[staIdx].staId, pAdapter->sessionId,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07005929 MAC_ADDR_ARRAY(mac));
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005930 sme_DeleteTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005931 pAdapter->sessionId,
5932 mac);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005933 }
5934 }
5935#endif
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05305936 status = wlan_hdd_disconnect(pAdapter, reasonCode);
5937 if ( 0 != status )
Jeff Johnson295189b2012-06-20 16:38:30 -07005938 {
5939 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05305940 "%s wlan_hdd_disconnect failure, returned %d \n",
Jeff Johnson295189b2012-06-20 16:38:30 -07005941 __func__, (int)status );
5942 return -EINVAL;
5943 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005944 }
5945 }
5946 else
5947 {
5948 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
5949 }
5950
5951 return status;
5952}
5953
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05305954
Jeff Johnson295189b2012-06-20 16:38:30 -07005955/*
5956 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305957 * This function is used to initialize the security
Jeff Johnson295189b2012-06-20 16:38:30 -07005958 * settings in IBSS mode.
5959 */
5960static int wlan_hdd_cfg80211_set_privacy_ibss(
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305961 hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07005962 struct cfg80211_ibss_params *params
5963 )
5964{
5965 int status = 0;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305966 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005967 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5968 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305969
Jeff Johnson295189b2012-06-20 16:38:30 -07005970 ENTER();
5971
5972 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5973
5974 if (params->ie_len && ( NULL != params->ie) )
5975 {
Shailender Karmuchi67edd312013-06-18 16:30:48 -07005976 if (wlan_hdd_cfg80211_get_ie_ptr (params->ie,
5977 params->ie_len, WLAN_EID_RSN ))
Jeff Johnson295189b2012-06-20 16:38:30 -07005978 {
5979 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5980 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5981 }
Shailender Karmuchi67edd312013-06-18 16:30:48 -07005982 else if ( hdd_isWPAIEPresent (params->ie, params->ie_len ))
Jeff Johnson295189b2012-06-20 16:38:30 -07005983 {
Shailender Karmuchi642e9812013-05-30 14:34:49 -07005984 tDot11fIEWPA dot11WPAIE;
5985 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
Shailender Karmuchi67edd312013-06-18 16:30:48 -07005986 u8 *ie;
Shailender Karmuchi642e9812013-05-30 14:34:49 -07005987
Shailender Karmuchi67edd312013-06-18 16:30:48 -07005988 ie = wlan_hdd_cfg80211_get_ie_ptr (params->ie,
5989 params->ie_len, DOT11F_EID_WPA);
5990 if ( NULL != ie )
5991 {
5992 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5993 // Unpack the WPA IE
5994 //Skip past the EID byte and length byte - and four byte WiFi OUI
5995 dot11fUnpackIeWPA((tpAniSirGlobal) halHandle,
5996 &ie[2+4],
5997 ie[1] - 4,
5998 &dot11WPAIE);
5999 /*Extract the multicast cipher, the encType for unicast
6000 cipher for wpa-none is none*/
6001 encryptionType =
6002 hdd_TranslateWPAToCsrEncryptionType(dot11WPAIE.multicast_cipher);
6003 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006004 }
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006005
Jeff Johnson295189b2012-06-20 16:38:30 -07006006 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
6007
6008 if (0 > status)
6009 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306010 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
Jeff Johnson295189b2012-06-20 16:38:30 -07006011 __func__);
6012 return status;
6013 }
6014 }
6015
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306016 pWextState->roamProfile.AuthType.authType[0] =
6017 pHddStaCtx->conn_info.authType =
Jeff Johnson295189b2012-06-20 16:38:30 -07006018 eCSR_AUTH_TYPE_OPEN_SYSTEM;
6019
6020 if (params->privacy)
6021 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306022 /* Security enabled IBSS, At this time there is no information available
6023 * about the security paramters, so initialise the encryption type to
Jeff Johnson295189b2012-06-20 16:38:30 -07006024 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306025 * The correct security parameters will be updated later in
Jeff Johnson295189b2012-06-20 16:38:30 -07006026 * wlan_hdd_cfg80211_add_key */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306027 /* Hal expects encryption type to be set inorder
Jeff Johnson295189b2012-06-20 16:38:30 -07006028 *enable privacy bit in beacons */
6029
6030 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
6031 }
Shailender Karmuchi642e9812013-05-30 14:34:49 -07006032 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
6033 "encryptionType=%d", encryptionType);
Jeff Johnson295189b2012-06-20 16:38:30 -07006034 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
6035 pWextState->roamProfile.EncryptionType.numEntries = 1;
6036 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
Jeff Johnson295189b2012-06-20 16:38:30 -07006037 return status;
6038}
6039
6040/*
6041 * FUNCTION: wlan_hdd_cfg80211_join_ibss
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306042 * This function is used to create/join an IBSS
Jeff Johnson295189b2012-06-20 16:38:30 -07006043 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306044static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006045 struct net_device *dev,
6046 struct cfg80211_ibss_params *params
6047 )
6048{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306049 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07006050 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6051 tCsrRoamProfile *pRoamProfile;
6052 int status;
6053 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306054 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006055
6056 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306057
6058 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07006059 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
6060
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306061 status = wlan_hdd_validate_context(pHddCtx);
6062
6063 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07006064 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306065 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6066 "%s: HDD context is not valid", __func__);
6067 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006068 }
6069
6070 if (NULL == pWextState)
6071 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306072 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07006073 __func__);
6074 return -EIO;
6075 }
6076
6077 pRoamProfile = &pWextState->roamProfile;
6078
6079 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
6080 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306081 hddLog (VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006082 "%s Interface type is not set to IBSS \n", __func__);
6083 return -EINVAL;
6084 }
6085
6086 /* Set Channel */
Yue Maf49ba872013-08-19 12:04:25 -07006087 if (NULL !=
6088#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
6089 params->chandef.chan)
6090#else
6091 params->channel)
6092#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006093 {
6094 u8 channelNum;
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006095 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6096 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
6097 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
6098 int indx;
Jeff Johnson295189b2012-06-20 16:38:30 -07006099
6100 /* Get channel number */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306101 channelNum =
Yue Maf49ba872013-08-19 12:04:25 -07006102 ieee80211_frequency_to_channel(
6103#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
6104 params->chandef.chan->center_freq);
6105#else
6106 params->channel->center_freq);
6107#endif
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006108
6109 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
6110 validChan, &numChans))
Jeff Johnson295189b2012-06-20 16:38:30 -07006111 {
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006112 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
6113 __func__);
6114 return -EOPNOTSUPP;
Jeff Johnson295189b2012-06-20 16:38:30 -07006115 }
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006116
6117 for (indx = 0; indx < numChans; indx++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006118 {
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006119 if (channelNum == validChan[indx])
6120 {
6121 break;
6122 }
6123 }
6124 if (indx >= numChans)
6125 {
6126 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07006127 __func__, channelNum);
6128 return -EINVAL;
6129 }
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006130 /* Set the Operational Channel */
6131 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
6132 channelNum);
6133 pRoamProfile->ChannelInfo.numOfChannels = 1;
6134 pHddStaCtx->conn_info.operationChannel = channelNum;
6135 pRoamProfile->ChannelInfo.ChannelList =
6136 &pHddStaCtx->conn_info.operationChannel;
Jeff Johnson295189b2012-06-20 16:38:30 -07006137 }
6138
6139 /* Initialize security parameters */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306140 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
Jeff Johnson295189b2012-06-20 16:38:30 -07006141 if (status < 0)
6142 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306143 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
Jeff Johnson295189b2012-06-20 16:38:30 -07006144 __func__);
6145 return status;
6146 }
6147
6148 /* Issue connect start */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306149 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006150 params->ssid_len, params->bssid,
6151 pHddStaCtx->conn_info.operationChannel);
Jeff Johnson295189b2012-06-20 16:38:30 -07006152
6153 if (0 > status)
6154 {
6155 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
6156 return status;
6157 }
6158
6159 return 0;
6160}
6161
6162/*
6163 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306164 * This function is used to leave an IBSS
Jeff Johnson295189b2012-06-20 16:38:30 -07006165 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306166static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006167 struct net_device *dev
6168 )
6169{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306170 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07006171 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6172 tCsrRoamProfile *pRoamProfile;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306173 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6174 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006175
6176 ENTER();
6177
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306178 status = wlan_hdd_validate_context(pHddCtx);
6179
6180 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006181 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306182 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6183 "%s: HDD context is not valid", __func__);
6184 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006185 }
6186
Jeff Johnson295189b2012-06-20 16:38:30 -07006187 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
6188 if (NULL == pWextState)
6189 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306190 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07006191 __func__);
6192 return -EIO;
6193 }
6194
6195 pRoamProfile = &pWextState->roamProfile;
6196
6197 /* Issue disconnect only if interface type is set to IBSS */
6198 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
6199 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306200 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
Jeff Johnson295189b2012-06-20 16:38:30 -07006201 __func__);
6202 return -EINVAL;
6203 }
6204
6205 /* Issue Disconnect request */
6206 INIT_COMPLETION(pAdapter->disconnect_comp_var);
6207 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6208 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6209
6210 return 0;
6211}
6212
6213/*
6214 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
6215 * This function is used to set the phy parameters
6216 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
6217 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306218static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006219 u32 changed)
6220{
6221 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6222 tHalHandle hHal = pHddCtx->hHal;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306223 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006224
6225 ENTER();
6226
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306227 status = wlan_hdd_validate_context(pHddCtx);
6228
6229 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006230 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306231 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6232 "%s: HDD context is not valid", __func__);
6233 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006234 }
6235
Jeff Johnson295189b2012-06-20 16:38:30 -07006236 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
6237 {
6238 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
6239 WNI_CFG_RTS_THRESHOLD_STAMAX :
6240 wiphy->rts_threshold;
6241
6242 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306243 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
Jeff Johnson295189b2012-06-20 16:38:30 -07006244 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306245 hddLog(VOS_TRACE_LEVEL_ERROR,
6246 "%s: Invalid RTS Threshold value %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006247 __func__, rts_threshold);
6248 return -EINVAL;
6249 }
6250
6251 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
6252 rts_threshold, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306253 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07006254 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306255 hddLog(VOS_TRACE_LEVEL_ERROR,
6256 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006257 __func__, rts_threshold);
6258 return -EIO;
6259 }
6260
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306261 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07006262 rts_threshold);
6263 }
6264
6265 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
6266 {
6267 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
6268 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
6269 wiphy->frag_threshold;
6270
6271 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306272 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
Jeff Johnson295189b2012-06-20 16:38:30 -07006273 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306274 hddLog(VOS_TRACE_LEVEL_ERROR,
6275 "%s: Invalid frag_threshold value %hu", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07006276 frag_threshold);
6277 return -EINVAL;
6278 }
6279
6280 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
6281 frag_threshold, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306282 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07006283 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306284 hddLog(VOS_TRACE_LEVEL_ERROR,
6285 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006286 __func__, frag_threshold);
6287 return -EIO;
6288 }
6289
6290 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
6291 frag_threshold);
6292 }
6293
6294 if ((changed & WIPHY_PARAM_RETRY_SHORT)
6295 || (changed & WIPHY_PARAM_RETRY_LONG))
6296 {
6297 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
6298 wiphy->retry_short :
6299 wiphy->retry_long;
6300
6301 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
6302 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
6303 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306304 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006305 __func__, retry_value);
6306 return -EINVAL;
6307 }
6308
6309 if (changed & WIPHY_PARAM_RETRY_SHORT)
6310 {
6311 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
6312 retry_value, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306313 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07006314 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306315 hddLog(VOS_TRACE_LEVEL_ERROR,
6316 "%s: ccmCfgSetInt failed for long retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006317 __func__, retry_value);
6318 return -EIO;
6319 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306320 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006321 __func__, retry_value);
6322 }
6323 else if (changed & WIPHY_PARAM_RETRY_SHORT)
6324 {
6325 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
6326 retry_value, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306327 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07006328 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306329 hddLog(VOS_TRACE_LEVEL_ERROR,
6330 "%s: ccmCfgSetInt failed for short retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006331 __func__, retry_value);
6332 return -EIO;
6333 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306334 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006335 __func__, retry_value);
6336 }
6337 }
6338
6339 return 0;
6340}
6341
6342/*
6343 * FUNCTION: wlan_hdd_cfg80211_set_txpower
6344 * This function is used to set the txpower
6345 */
6346static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
Yue Maf49ba872013-08-19 12:04:25 -07006347#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
6348 struct wireless_dev *wdev,
6349#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006350#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306351 enum tx_power_setting type,
Jeff Johnson295189b2012-06-20 16:38:30 -07006352#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306353 enum nl80211_tx_power_setting type,
Jeff Johnson295189b2012-06-20 16:38:30 -07006354#endif
6355 int dbm)
6356{
6357 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306358 tHalHandle hHal = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006359 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
6360 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306361 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006362
6363 ENTER();
6364
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306365 status = wlan_hdd_validate_context(pHddCtx);
6366
6367 if (0 != status)
6368 {
6369 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6370 "%s: HDD context is not valid", __func__);
6371 return status;
6372 }
6373
6374 hHal = pHddCtx->hHal;
6375
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306376 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
6377 dbm, ccmCfgSetCallback,
6378 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07006379 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306380 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006381 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
6382 return -EIO;
6383 }
6384
6385 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
6386 dbm);
6387
6388 switch(type)
6389 {
6390 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
6391 /* Fall through */
6392 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
6393 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
6394 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306395 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
6396 __func__);
6397 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006398 }
6399 break;
6400 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306401 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
Jeff Johnson295189b2012-06-20 16:38:30 -07006402 __func__);
6403 return -EOPNOTSUPP;
6404 break;
6405 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306406 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
6407 __func__, type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006408 return -EIO;
6409 }
6410
6411 return 0;
6412}
6413
6414/*
6415 * FUNCTION: wlan_hdd_cfg80211_get_txpower
6416 * This function is used to read the txpower
6417 */
Yue Maf49ba872013-08-19 12:04:25 -07006418static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy,
6419#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
6420 struct wireless_dev *wdev,
6421#endif
6422 int *dbm)
Jeff Johnson295189b2012-06-20 16:38:30 -07006423{
6424
6425 hdd_adapter_t *pAdapter;
6426 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306427 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006428
Jeff Johnsone7245742012-09-05 17:12:55 -07006429 ENTER();
6430
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306431 status = wlan_hdd_validate_context(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006432
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306433 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006434 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306435 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6436 "%s: HDD context is not valid", __func__);
6437 *dbm = 0;
6438 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006439 }
6440
Jeff Johnson295189b2012-06-20 16:38:30 -07006441 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
6442 if (NULL == pAdapter)
6443 {
6444 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
6445 return -ENOENT;
6446 }
6447
6448 wlan_hdd_get_classAstats(pAdapter);
6449 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
6450
Jeff Johnsone7245742012-09-05 17:12:55 -07006451 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006452 return 0;
6453}
6454
6455static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
6456 u8* mac, struct station_info *sinfo)
6457{
6458 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
6459 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6460 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
6461 tANI_U8 rate_flags;
6462
6463 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6464 hdd_config_t *pCfg = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07006465
6466 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
6467 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
6468 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
6469 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
6470 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
6471 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
6472 tANI_U16 maxRate = 0;
6473 tANI_U16 myRate;
6474 tANI_U16 currentRate = 0;
6475 tANI_U8 maxSpeedMCS = 0;
6476 tANI_U8 maxMCSIdx = 0;
6477 tANI_U8 rateFlag = 1;
6478 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006479 tANI_U16 temp;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306480 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006481
Leo Chang6f8870f2013-03-26 18:11:36 -07006482#ifdef WLAN_FEATURE_11AC
6483 tANI_U32 vht_mcs_map;
6484 eDataRate11ACMaxMcs vhtMaxMcs;
6485#endif /* WLAN_FEATURE_11AC */
6486
Jeff Johnsone7245742012-09-05 17:12:55 -07006487 ENTER();
6488
Jeff Johnson295189b2012-06-20 16:38:30 -07006489 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
6490 (0 == ssidlen))
6491 {
6492 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
6493 " Invalid ssidlen, %d", __func__, ssidlen);
6494 /*To keep GUI happy*/
6495 return 0;
6496 }
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 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
6508 sinfo->filled |= STATION_INFO_SIGNAL;
6509
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006510 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006511 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
6512
6513 //convert to the UI units of 100kbps
6514 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
6515
6516#ifdef LINKSPEED_DEBUG_ENABLED
Leo Chang6f8870f2013-03-26 18:11:36 -07006517 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 -07006518 sinfo->signal,
6519 pCfg->reportMaxLinkSpeed,
6520 myRate,
6521 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006522 (int) pCfg->linkSpeedRssiMid,
6523 (int) pCfg->linkSpeedRssiLow,
Leo Chang6f8870f2013-03-26 18:11:36 -07006524 (int) rate_flags,
6525 (int) pAdapter->hdd_stats.ClassA_stat.mcs_index);
Jeff Johnson295189b2012-06-20 16:38:30 -07006526#endif //LINKSPEED_DEBUG_ENABLED
6527
6528 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
6529 {
6530 // we do not want to necessarily report the current speed
6531 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
6532 {
6533 // report the max possible speed
6534 rssidx = 0;
6535 }
6536 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
6537 {
6538 // report the max possible speed with RSSI scaling
6539 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
6540 {
6541 // report the max possible speed
6542 rssidx = 0;
6543 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006544 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07006545 {
6546 // report middle speed
6547 rssidx = 1;
6548 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006549 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
6550 {
6551 // report middle speed
6552 rssidx = 2;
6553 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006554 else
6555 {
6556 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006557 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07006558 }
6559 }
6560 else
6561 {
6562 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
6563 hddLog(VOS_TRACE_LEVEL_ERROR,
6564 "%s: Invalid value for reportMaxLinkSpeed: %u",
6565 __func__, pCfg->reportMaxLinkSpeed);
6566 rssidx = 0;
6567 }
6568
6569 maxRate = 0;
6570
6571 /* Get Basic Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306572 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_OPERATIONAL_RATE_SET,
6573 OperationalRates, &ORLeng))
6574 {
6575 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6576 /*To keep GUI happy*/
6577 return 0;
6578 }
6579
Jeff Johnson295189b2012-06-20 16:38:30 -07006580 for (i = 0; i < ORLeng; i++)
6581 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006582 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006583 {
6584 /* Validate Rate Set */
6585 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
6586 {
6587 currentRate = supported_data_rate[j].supported_rate[rssidx];
6588 break;
6589 }
6590 }
6591 /* Update MAX rate */
6592 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6593 }
6594
6595 /* Get Extended Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306596 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
6597 ExtendedRates, &ERLeng))
6598 {
6599 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6600 /*To keep GUI happy*/
6601 return 0;
6602 }
6603
Jeff Johnson295189b2012-06-20 16:38:30 -07006604 for (i = 0; i < ERLeng; i++)
6605 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006606 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006607 {
6608 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
6609 {
6610 currentRate = supported_data_rate[j].supported_rate[rssidx];
6611 break;
6612 }
6613 }
6614 /* Update MAX rate */
6615 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6616 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006617 /* Get MCS Rate Set -- but only if we are connected at MCS
6618 rates or if we are always reporting max speed or if we have
6619 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006620 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07006621 {
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306622 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_CURRENT_MCS_SET,
6623 MCSRates, &MCSLeng))
6624 {
6625 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6626 /*To keep GUI happy*/
6627 return 0;
6628 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006629 rateFlag = 0;
Leo Chang6f8870f2013-03-26 18:11:36 -07006630#ifdef WLAN_FEATURE_11AC
6631 /* VHT80 rate has seperate rate table */
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306632 if (rate_flags & (eHAL_TX_RATE_VHT20|eHAL_TX_RATE_VHT40|eHAL_TX_RATE_VHT80))
Jeff Johnson295189b2012-06-20 16:38:30 -07006633 {
Leo Chang6f8870f2013-03-26 18:11:36 -07006634 ccmCfgGetInt(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_VHT_TX_MCS_MAP, &vht_mcs_map);
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306635 vhtMaxMcs = (eDataRate11ACMaxMcs)(vht_mcs_map & DATA_RATE_11AC_MCS_MASK );
Leo Chang6f8870f2013-03-26 18:11:36 -07006636 if (rate_flags & eHAL_TX_RATE_SGI)
Jeff Johnson295189b2012-06-20 16:38:30 -07006637 {
Leo Chang6f8870f2013-03-26 18:11:36 -07006638 rateFlag |= 1;
Jeff Johnson295189b2012-06-20 16:38:30 -07006639 }
Leo Chang6f8870f2013-03-26 18:11:36 -07006640 if (DATA_RATE_11AC_MAX_MCS_7 == vhtMaxMcs)
Jeff Johnson295189b2012-06-20 16:38:30 -07006641 {
Leo Chang6f8870f2013-03-26 18:11:36 -07006642 maxMCSIdx = 7;
6643 }
6644 else if (DATA_RATE_11AC_MAX_MCS_8 == vhtMaxMcs)
6645 {
6646 maxMCSIdx = 8;
6647 }
6648 else if (DATA_RATE_11AC_MAX_MCS_9 == vhtMaxMcs)
6649 {
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306650 //VHT20 is supporting 0~8
6651 if (rate_flags & eHAL_TX_RATE_VHT20)
6652 maxMCSIdx = 8;
6653 else
6654 maxMCSIdx = 9;
Leo Chang6f8870f2013-03-26 18:11:36 -07006655 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306656
6657 if (rate_flags & eHAL_TX_RATE_VHT80)
6658 {
6659 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT80_rate[rateFlag];
6660 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT80_rate[rateFlag];
6661 }
6662 else if (rate_flags & eHAL_TX_RATE_VHT40)
6663 {
6664 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT40_rate[rateFlag];
6665 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT40_rate[rateFlag];
6666 }
6667 else if (rate_flags & eHAL_TX_RATE_VHT20)
6668 {
6669 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT20_rate[rateFlag];
6670 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT20_rate[rateFlag];
6671 }
6672
Leo Chang6f8870f2013-03-26 18:11:36 -07006673 maxSpeedMCS = 1;
6674 if (currentRate > maxRate)
6675 {
6676 maxRate = currentRate;
6677 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306678
Leo Chang6f8870f2013-03-26 18:11:36 -07006679 }
6680 else
6681#endif /* WLAN_FEATURE_11AC */
6682 {
6683 if (rate_flags & eHAL_TX_RATE_HT40)
6684 {
6685 rateFlag |= 1;
6686 }
6687 if (rate_flags & eHAL_TX_RATE_SGI)
6688 {
6689 rateFlag |= 2;
6690 }
6691
6692 for (i = 0; i < MCSLeng; i++)
6693 {
6694 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
6695 for (j = 0; j < temp; j++)
6696 {
6697 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
6698 {
6699 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
6700 break;
6701 }
6702 }
6703 if ((j < temp) && (currentRate > maxRate))
6704 {
6705 maxRate = currentRate;
6706 maxSpeedMCS = 1;
6707 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
6708 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006709 }
6710 }
6711 }
6712
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306713 else if (!(rate_flags & eHAL_TX_RATE_LEGACY))
6714 {
6715 maxRate = myRate;
6716 maxSpeedMCS = 1;
6717 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6718 }
6719
Jeff Johnson295189b2012-06-20 16:38:30 -07006720 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006721 if (((maxRate < myRate) && (0 == rssidx)) ||
6722 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006723 {
6724 maxRate = myRate;
6725 if (rate_flags & eHAL_TX_RATE_LEGACY)
6726 {
6727 maxSpeedMCS = 0;
6728 }
6729 else
6730 {
6731 maxSpeedMCS = 1;
6732 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6733 }
6734 }
6735
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306736 if (rate_flags & eHAL_TX_RATE_LEGACY)
Jeff Johnson295189b2012-06-20 16:38:30 -07006737 {
6738 sinfo->txrate.legacy = maxRate;
6739#ifdef LINKSPEED_DEBUG_ENABLED
6740 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
6741#endif //LINKSPEED_DEBUG_ENABLED
6742 }
6743 else
6744 {
6745 sinfo->txrate.mcs = maxMCSIdx;
Leo Chang6f8870f2013-03-26 18:11:36 -07006746#ifdef WLAN_FEATURE_11AC
6747 sinfo->txrate.nss = 1;
6748 if (rate_flags & eHAL_TX_RATE_VHT80)
6749 {
6750 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306751 sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Leo Chang6f8870f2013-03-26 18:11:36 -07006752 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306753 else if (rate_flags & eHAL_TX_RATE_VHT40)
Leo Chang6f8870f2013-03-26 18:11:36 -07006754 {
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306755 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
6756 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6757 }
6758 else if (rate_flags & eHAL_TX_RATE_VHT20)
6759 {
6760 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
6761 }
6762#endif /* WLAN_FEATURE_11AC */
6763 if (rate_flags & (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40))
6764 {
6765 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6766 if (rate_flags & eHAL_TX_RATE_HT40)
6767 {
6768 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6769 }
Leo Chang6f8870f2013-03-26 18:11:36 -07006770 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006771 if (rate_flags & eHAL_TX_RATE_SGI)
6772 {
6773 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6774 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306775
Jeff Johnson295189b2012-06-20 16:38:30 -07006776#ifdef LINKSPEED_DEBUG_ENABLED
6777 pr_info("Reporting MCS rate %d flags %x\n",
6778 sinfo->txrate.mcs,
6779 sinfo->txrate.flags );
6780#endif //LINKSPEED_DEBUG_ENABLED
6781 }
6782 }
6783 else
6784 {
6785 // report current rate instead of max rate
6786
6787 if (rate_flags & eHAL_TX_RATE_LEGACY)
6788 {
6789 //provide to the UI in units of 100kbps
6790 sinfo->txrate.legacy = myRate;
6791#ifdef LINKSPEED_DEBUG_ENABLED
6792 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
6793#endif //LINKSPEED_DEBUG_ENABLED
6794 }
6795 else
6796 {
6797 //must be MCS
6798 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
Leo Chang6f8870f2013-03-26 18:11:36 -07006799#ifdef WLAN_FEATURE_11AC
6800 sinfo->txrate.nss = 1;
6801 if (rate_flags & eHAL_TX_RATE_VHT80)
6802 {
6803 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
6804 }
6805 else
6806#endif /* WLAN_FEATURE_11AC */
6807 {
6808 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6809 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006810 if (rate_flags & eHAL_TX_RATE_SGI)
6811 {
6812 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6813 }
6814 if (rate_flags & eHAL_TX_RATE_HT40)
6815 {
6816 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6817 }
Leo Chang6f8870f2013-03-26 18:11:36 -07006818#ifdef WLAN_FEATURE_11AC
6819 else if (rate_flags & eHAL_TX_RATE_VHT80)
6820 {
6821 sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
6822 }
6823#endif /* WLAN_FEATURE_11AC */
Jeff Johnson295189b2012-06-20 16:38:30 -07006824#ifdef LINKSPEED_DEBUG_ENABLED
6825 pr_info("Reporting actual MCS rate %d flags %x\n",
6826 sinfo->txrate.mcs,
6827 sinfo->txrate.flags );
6828#endif //LINKSPEED_DEBUG_ENABLED
6829 }
6830 }
6831 sinfo->filled |= STATION_INFO_TX_BITRATE;
6832
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006833 sinfo->tx_packets =
6834 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
6835 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
6836 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
6837 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
6838
6839 sinfo->tx_retries =
6840 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
6841 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
6842 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
6843 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
6844
6845 sinfo->tx_failed =
6846 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
6847 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
6848 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
6849 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
6850
6851 sinfo->filled |=
6852 STATION_INFO_TX_PACKETS |
6853 STATION_INFO_TX_RETRIES |
6854 STATION_INFO_TX_FAILED;
6855
6856 EXIT();
6857 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006858}
6859
6860static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
Sameer Thalappilc9f26e92013-06-07 10:11:06 -07006861 struct net_device *dev, bool mode, int timeout)
Jeff Johnson295189b2012-06-20 16:38:30 -07006862{
6863 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05306864 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07006865 VOS_STATUS vos_status;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306866 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006867
Jeff Johnsone7245742012-09-05 17:12:55 -07006868 ENTER();
6869
Jeff Johnson295189b2012-06-20 16:38:30 -07006870 if (NULL == pAdapter)
6871 {
6872 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6873 return -ENODEV;
6874 }
6875
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05306876 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306877 status = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05306878
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306879 if (0 != status)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306880 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306881 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6882 "%s: HDD context is not valid", __func__);
6883 return status;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306884 }
6885
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05306886 if ((DRIVER_POWER_MODE_AUTO == !mode) &&
6887 (TRUE == pHddCtx->hdd_wlan_suspended) &&
6888 (pHddCtx->cfg_ini->fhostArpOffload) &&
6889 (eConnectionState_Associated ==
6890 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
6891 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05306892 vos_status = hdd_conf_arp_offload(pAdapter, TRUE);
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05306893 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6894 {
6895 hddLog(VOS_TRACE_LEVEL_INFO,
6896 "%s:Failed to enable ARPOFFLOAD Feature %d\n",
6897 __func__, vos_status);
6898 }
6899 }
6900
Jeff Johnson295189b2012-06-20 16:38:30 -07006901 /**The get power cmd from the supplicant gets updated by the nl only
6902 *on successful execution of the function call
6903 *we are oppositely mapped w.r.t mode in the driver
6904 **/
6905 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
6906
Jeff Johnsone7245742012-09-05 17:12:55 -07006907 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006908 if (VOS_STATUS_E_FAILURE == vos_status)
6909 {
6910 return -EINVAL;
6911 }
6912 return 0;
6913}
6914
6915
6916#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6917static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
6918 struct net_device *netdev,
6919 u8 key_index)
6920{
Jeff Johnsone7245742012-09-05 17:12:55 -07006921 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006922 return 0;
6923}
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306924#endif //LINUX_VERSION_CODE
Jeff Johnson295189b2012-06-20 16:38:30 -07006925
6926#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
6927static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6928 struct net_device *dev,
6929 struct ieee80211_txq_params *params)
6930{
Jeff Johnsone7245742012-09-05 17:12:55 -07006931 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006932 return 0;
6933}
6934#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6935static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6936 struct ieee80211_txq_params *params)
6937{
Jeff Johnsone7245742012-09-05 17:12:55 -07006938 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006939 return 0;
6940}
6941#endif //LINUX_VERSION_CODE
6942
6943static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
6944 struct net_device *dev, u8 *mac)
6945{
6946 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306947 hdd_context_t *pHddCtx;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006948 VOS_STATUS vos_status;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306949 int status;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006950 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006951
Jeff Johnsone7245742012-09-05 17:12:55 -07006952 ENTER();
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306953 if ( NULL == pAdapter )
Jeff Johnson295189b2012-06-20 16:38:30 -07006954 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306955 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006956 return -EINVAL;
6957 }
6958
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306959 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6960 status = wlan_hdd_validate_context(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006961
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306962 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006963 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306964 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6965 "%s: HDD context is not valid", __func__);
6966 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006967 }
6968
Jeff Johnson295189b2012-06-20 16:38:30 -07006969 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006970 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006971 )
6972 {
6973 if( NULL == mac )
6974 {
6975 v_U16_t i;
6976 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
6977 {
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07006978 if ((pAdapter->aStaInfo[i].isUsed) &&
6979 (!pAdapter->aStaInfo[i].isDeauthInProgress))
Jeff Johnson295189b2012-06-20 16:38:30 -07006980 {
6981 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
6982 hddLog(VOS_TRACE_LEVEL_INFO,
6983 "%s: Delete STA with MAC::"
6984 "%02x:%02x:%02x:%02x:%02x:%02x",
6985 __func__,
6986 macAddr[0], macAddr[1], macAddr[2],
6987 macAddr[3], macAddr[4], macAddr[5]);
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07006988 vos_status = hdd_softap_sta_deauth(pAdapter, macAddr);
6989 if (VOS_IS_STATUS_SUCCESS(vos_status))
6990 pAdapter->aStaInfo[i].isDeauthInProgress = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006991 }
6992 }
6993 }
6994 else
6995 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006996
6997 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
6998 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6999 {
7000 hddLog(VOS_TRACE_LEVEL_INFO,
7001 "%s: Skip this DEL STA as this is not used::"
7002 "%02x:%02x:%02x:%02x:%02x:%02x",
7003 __func__,
7004 mac[0], mac[1], mac[2],
7005 mac[3], mac[4], mac[5]);
7006 return -ENOENT;
7007 }
7008
7009 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
7010 {
7011 hddLog(VOS_TRACE_LEVEL_INFO,
7012 "%s: Skip this DEL STA as deauth is in progress::"
7013 "%02x:%02x:%02x:%02x:%02x:%02x",
7014 __func__,
7015 mac[0], mac[1], mac[2],
7016 mac[3], mac[4], mac[5]);
7017 return -ENOENT;
7018 }
7019
7020 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
7021
Jeff Johnson295189b2012-06-20 16:38:30 -07007022 hddLog(VOS_TRACE_LEVEL_INFO,
7023 "%s: Delete STA with MAC::"
7024 "%02x:%02x:%02x:%02x:%02x:%02x",
7025 __func__,
7026 mac[0], mac[1], mac[2],
7027 mac[3], mac[4], mac[5]);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007028
7029 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
7030 if (!VOS_IS_STATUS_SUCCESS(vos_status))
7031 {
7032 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
7033 hddLog(VOS_TRACE_LEVEL_INFO,
7034 "%s: STA removal failed for ::"
7035 "%02x:%02x:%02x:%02x:%02x:%02x",
7036 __func__,
7037 mac[0], mac[1], mac[2],
7038 mac[3], mac[4], mac[5]);
7039 return -ENOENT;
7040 }
7041
Jeff Johnson295189b2012-06-20 16:38:30 -07007042 }
7043 }
7044
7045 EXIT();
7046
7047 return 0;
7048}
7049
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007050static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
7051 struct net_device *dev, u8 *mac, struct station_parameters *params)
7052{
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007053 int status = -EPERM;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007054#ifdef FEATURE_WLAN_TDLS
7055 u32 mask, set;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007056 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007057 mask = params->sta_flags_mask;
7058
7059 set = params->sta_flags_set;
7060
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007061#ifdef WLAN_FEATURE_TDLS_DEBUG
7062 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7063 "%s: mask 0x%x set 0x%x " MAC_ADDRESS_STR,
7064 __func__, mask, set, MAC_ADDR_ARRAY(mac));
7065#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007066
7067 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
7068 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08007069 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007070 }
7071 }
7072#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007073 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07007074}
7075
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007076
7077#ifdef FEATURE_WLAN_LFR
7078static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07007079 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007080{
7081#define MAX_PMKSAIDS_IN_CACHE 8
7082 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307083 static tANI_U32 i; // HDD Local Cache index
7084 tANI_U32 j=0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007085 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7086 tHalHandle halHandle;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307087 eHalStatus result;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307088 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007089 tANI_U8 BSSIDMatched = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307090 hdd_context_t *pHddCtx;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307091
Jeff Johnsone7245742012-09-05 17:12:55 -07007092 ENTER();
7093
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307094 // Validate pAdapter
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307095 if ( NULL == pAdapter )
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007096 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307097 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007098 return -EINVAL;
7099 }
7100
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307101 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7102 status = wlan_hdd_validate_context(pHddCtx);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007103
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307104 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007105 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307106 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7107 "%s: HDD context is not valid", __func__);
7108 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007109 }
7110
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307111 // Retrieve halHandle
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007112 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
7113
7114 for (j = 0; j < i; j++)
7115 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307116 if(vos_mem_compare(PMKIDCache[j].BSSID,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007117 pmksa->bssid, WNI_CFG_BSSID_LEN))
7118 {
7119 /* BSSID matched previous entry. Overwrite it. */
7120 BSSIDMatched = 1;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307121 vos_mem_copy(PMKIDCache[j].BSSID,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007122 pmksa->bssid, WNI_CFG_BSSID_LEN);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307123 vos_mem_copy(PMKIDCache[j].PMKID,
7124 pmksa->pmkid,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007125 CSR_RSN_PMKID_SIZE);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307126 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007127 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007128 dump_bssid(pmksa->bssid);
7129 dump_pmkid(halHandle, pmksa->pmkid);
7130 break;
7131 }
7132 }
7133
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07007134 /* Check we compared all entries,if then take the first slot now */
7135 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
7136
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007137 if (!BSSIDMatched)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307138 {
7139 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
7140 vos_mem_copy(PMKIDCache[i].BSSID,
7141 pmksa->bssid, ETHER_ADDR_LEN);
7142 vos_mem_copy(PMKIDCache[i].PMKID,
7143 pmksa->pmkid,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007144 CSR_RSN_PMKID_SIZE);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307145 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007146 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007147 dump_bssid(pmksa->bssid);
7148 dump_pmkid(halHandle, pmksa->pmkid);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307149 // Increment the HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007150 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307151 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007152 }
7153
7154
7155 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307156 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007157 // __func__, i );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307158 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007159 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007160 // Finally set the PMKSA ID Cache in CSR
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307161 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
7162 PMKIDCache,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007163 i );
7164 return 0;
7165}
7166
7167
7168static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07007169 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007170{
Jeff Johnsone7245742012-09-05 17:12:55 -07007171 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007172 // TODO: Implement this later.
7173 return 0;
7174}
7175
7176static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
7177{
Jeff Johnsone7245742012-09-05 17:12:55 -07007178 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007179 // TODO: Implement this later.
7180 return 0;
7181}
7182#endif
7183
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007184#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307185static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007186 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
7187{
7188 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7189 hdd_station_ctx_t *pHddStaCtx;
7190
7191 if (NULL == pAdapter)
7192 {
7193 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
7194 return -ENODEV;
7195 }
7196
7197 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7198
7199 // Added for debug on reception of Re-assoc Req.
7200 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
7201 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307202 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007203 ftie->ie_len);
7204 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
7205 }
7206
7207#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307208 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007209 ftie->ie_len);
7210#endif
7211
7212 // Pass the received FT IEs to SME
Gopichand Nakkala356fb102013-03-06 12:34:04 +05307213 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
7214 (const u8 *)ftie->ie,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007215 ftie->ie_len);
7216 return 0;
7217}
7218#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007219
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307220#ifdef FEATURE_WLAN_SCAN_PNO
7221
7222void hdd_cfg80211_sched_scan_done_callback(void *callbackContext,
7223 tSirPrefNetworkFoundInd *pPrefNetworkFoundInd)
7224{
7225 int ret;
7226 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
7227 hdd_context_t *pHddCtx;
7228
7229 if (NULL == pAdapter)
7230 {
7231 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7232 "%s: HDD adapter is Null", __func__);
7233 return ;
7234 }
7235
7236 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7237 if (NULL == pHddCtx)
7238 {
7239 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7240 "%s: HDD context is Null!!!", __func__);
7241 return ;
7242 }
7243
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307244 spin_lock(&pHddCtx->schedScan_lock);
7245 if (TRUE == pHddCtx->isWiphySuspended)
7246 {
7247 pHddCtx->isSchedScanUpdatePending = TRUE;
7248 spin_unlock(&pHddCtx->schedScan_lock);
7249 hddLog(VOS_TRACE_LEVEL_INFO,
7250 "%s: Update cfg80211 scan database after it resume", __func__);
7251 return ;
7252 }
7253 spin_unlock(&pHddCtx->schedScan_lock);
7254
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307255 ret = wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter);
7256
7257 if (0 > ret)
7258 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
7259
7260 cfg80211_sched_scan_results(pHddCtx->wiphy);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307261 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7262 "%s: cfg80211 scan result database updated", __func__);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307263}
7264
7265/*
7266 * FUNCTION: wlan_hdd_cfg80211_sched_scan_start
7267 * NL interface to enable PNO
7268 */
7269static int wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy,
7270 struct net_device *dev, struct cfg80211_sched_scan_request *request)
7271{
7272 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7273 tpSirPNOScanReq pPnoRequest = NULL;
7274 hdd_context_t *pHddCtx;
7275 tHalHandle hHal;
Madan Mohan Koyyalamudi1d16f462013-08-27 16:25:34 +05307276 v_U32_t i, indx, num_ch, tempInterval;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307277 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
7278 u8 channels_allowed[WNI_CFG_VALID_CHANNEL_LIST_LEN];
7279 v_U32_t num_channels_allowed = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7280 eHalStatus status = eHAL_STATUS_FAILURE;
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307281 int ret = 0;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307282
7283 if (NULL == pAdapter)
7284 {
7285 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7286 "%s: HDD adapter is Null", __func__);
7287 return -ENODEV;
7288 }
7289
7290 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307291 ret = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307292
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307293 if (0 != ret)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307294 {
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05307295 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7296 "%s: HDD context is not valid", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307297 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307298 }
7299
7300 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
7301 if (NULL == hHal)
7302 {
7303 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7304 "%s: HAL context is Null!!!", __func__);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307305 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307306 }
7307
7308 pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq));
7309 if (NULL == pPnoRequest)
7310 {
7311 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7312 "%s: vos_mem_malloc failed", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307313 return -ENOMEM;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307314 }
7315
7316 pPnoRequest->enable = 1; /*Enable PNO */
7317 pPnoRequest->ucNetworksCount = request->n_match_sets;
7318
7319 if (( !pPnoRequest->ucNetworksCount ) ||
7320 ( pPnoRequest->ucNetworksCount > SIR_PNO_MAX_SUPP_NETWORKS ))
7321 {
7322 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7323 "Network input is not correct");
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307324 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307325 goto error;
7326 }
7327
7328 if ( SIR_PNO_MAX_NETW_CHANNELS_EX < request->n_channels )
7329 {
7330 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7331 "Incorrect number of channels");
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307332 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307333 goto error;
7334 }
7335
7336 /* Framework provides one set of channels(all)
7337 * common for all saved profile */
7338 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
7339 channels_allowed, &num_channels_allowed))
7340 {
7341 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7342 "%s: failed to get valid channel list", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307343 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307344 goto error;
7345 }
7346 /* Checking each channel against allowed channel list */
7347 num_ch = 0;
7348 for (i = 0; i < request->n_channels; i++)
7349 {
7350 for (indx = 0; indx < num_channels_allowed; indx++)
7351 {
7352 if (request->channels[i]->hw_value == channels_allowed[indx])
7353 {
7354 valid_ch[num_ch++] = request->channels[i]->hw_value;
7355 break ;
7356 }
7357 }
7358 }
7359
7360 /* Filling per profile params */
7361 for (i = 0; i < pPnoRequest->ucNetworksCount; i++)
7362 {
7363 pPnoRequest->aNetworks[i].ssId.length =
7364 request->match_sets[i].ssid.ssid_len;
7365
7366 if (( 0 == pPnoRequest->aNetworks[i].ssId.length ) ||
7367 ( pPnoRequest->aNetworks[i].ssId.length > 32 ) )
7368 {
7369 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7370 "SSID Len %d is not correct for network %d",
7371 pPnoRequest->aNetworks[i].ssId.length, i);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307372 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307373 goto error;
7374 }
7375
7376 memcpy(pPnoRequest->aNetworks[i].ssId.ssId,
7377 request->match_sets[i].ssid.ssid,
7378 request->match_sets[i].ssid.ssid_len);
7379 pPnoRequest->aNetworks[i].authentication = 0; /*eAUTH_TYPE_ANY*/
7380 pPnoRequest->aNetworks[i].encryption = 0; /*eED_ANY*/
7381 pPnoRequest->aNetworks[i].bcastNetwType = 0; /*eBCAST_UNKNOWN*/
7382
7383 /*Copying list of valid channel into request */
7384 memcpy(pPnoRequest->aNetworks[i].aChannels, valid_ch, num_ch);
7385 pPnoRequest->aNetworks[i].ucChannelCount = num_ch;
7386
7387 pPnoRequest->aNetworks[i].rssiThreshold = 0; //Default value
7388 }
7389
Madan Mohan Koyyalamudi1d16f462013-08-27 16:25:34 +05307390 /* Driver gets only one time interval which is hardcoded in
7391 * supplicant for 10000ms. Taking power consumption into account 6 timers
7392 * will be used, Timervalue is increased exponentially i.e 10,20,40,
7393 * 80,160,320 secs. And number of scan cycle for each timer
7394 * is configurable through INI param gPNOScanTimerRepeatValue.
7395 * If it is set to 0 only one timer will be used and PNO scan cycle
7396 * will be repeated after each interval specified by supplicant
7397 * till PNO is disabled.
7398 */
7399 if (0 == pHddCtx->cfg_ini->configPNOScanTimerRepeatValue)
7400 pPnoRequest->scanTimers.ucScanTimersCount = HDD_PNO_SCAN_TIMERS_SET_ONE;
7401 else
7402 pPnoRequest->scanTimers.ucScanTimersCount =
7403 HDD_PNO_SCAN_TIMERS_SET_MULTIPLE;
7404
7405 tempInterval = (request->interval)/1000;
7406 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7407 "Base scan interval = %d PNOScanTimerRepeatValue = %d",
7408 tempInterval, pHddCtx->cfg_ini->configPNOScanTimerRepeatValue);
7409 for ( i = 0; i < pPnoRequest->scanTimers.ucScanTimersCount; i++)
7410 {
7411 pPnoRequest->scanTimers.aTimerValues[i].uTimerRepeat =
7412 pHddCtx->cfg_ini->configPNOScanTimerRepeatValue;
7413 pPnoRequest->scanTimers.aTimerValues[i].uTimerValue = tempInterval;
7414 tempInterval *= 2;
7415 }
7416 //Repeat last timer until pno disabled.
7417 pPnoRequest->scanTimers.aTimerValues[i-1].uTimerRepeat = 0;
7418
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307419 pPnoRequest->modePNO = SIR_PNO_MODE_ON_SUSPEND;
7420
7421 status = sme_SetPreferredNetworkList(WLAN_HDD_GET_HAL_CTX(pAdapter),
7422 pPnoRequest, pAdapter->sessionId,
7423 hdd_cfg80211_sched_scan_done_callback, pAdapter);
7424 if (eHAL_STATUS_SUCCESS != status)
7425 {
7426 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7427 "Failed to enable PNO");
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307428 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307429 goto error;
7430 }
7431
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307432 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7433 "PNO scanRequest offloaded");
7434
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307435error:
7436 vos_mem_free(pPnoRequest);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307437 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307438}
7439
7440/*
7441 * FUNCTION: wlan_hdd_cfg80211_sched_scan_stop
7442 * NL interface to disable PNO
7443 */
7444static int wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy,
7445 struct net_device *dev)
7446{
7447 eHalStatus status = eHAL_STATUS_FAILURE;
7448 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7449 hdd_context_t *pHddCtx;
7450 tHalHandle hHal;
7451 tpSirPNOScanReq pPnoRequest = NULL;
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307452 int ret = 0;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307453
7454 ENTER();
7455
7456 if (NULL == pAdapter)
7457 {
7458 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7459 "%s: HDD adapter is Null", __func__);
7460 return -ENODEV;
7461 }
7462
7463 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307464
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307465 if (NULL == pHddCtx)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307466 {
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05307467 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307468 "%s: HDD context is Null", __func__);
7469 return -ENODEV;
7470 }
7471
7472 /* The return 0 is intentional when isLogpInProgress and
7473 * isLoadUnloadInProgress. We did observe a crash due to a return of
7474 * failure in sched_scan_stop , especially for a case where the unload
7475 * of the happens at the same time. The function __cfg80211_stop_sched_scan
7476 * was clearing rdev->sched_scan_req only when the sched_scan_stop returns
7477 * success. If it returns a failure , then its next invocation due to the
7478 * clean up of the second interface will have the dev pointer corresponding
7479 * to the first one leading to a crash.
7480 */
7481 if (pHddCtx->isLogpInProgress)
7482 {
7483 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7484 "%s: LOGP in Progress. Ignore!!!", __func__);
7485 return ret;
7486 }
7487
7488 if (pHddCtx->isLoadUnloadInProgress)
7489 {
7490 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7491 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
7492 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307493 }
7494
7495 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
7496 if (NULL == hHal)
7497 {
7498 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7499 "%s: HAL context is Null!!!", __func__);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307500 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307501 }
7502
7503 pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq));
7504 if (NULL == pPnoRequest)
7505 {
7506 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7507 "%s: vos_mem_malloc failed", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307508 return -ENOMEM;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307509 }
7510
7511 memset(pPnoRequest, 0, sizeof (tSirPNOScanReq));
7512 pPnoRequest->enable = 0; /* Disable PNO */
7513 pPnoRequest->ucNetworksCount = 0;
7514
7515 status = sme_SetPreferredNetworkList(hHal, pPnoRequest,
7516 pAdapter->sessionId,
7517 NULL, pAdapter);
7518 if (eHAL_STATUS_SUCCESS != status)
7519 {
7520 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7521 "Failed to disabled PNO");
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307522 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307523 }
7524
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307525 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7526 "%s: PNO scan disabled", __func__);
7527
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307528 vos_mem_free(pPnoRequest);
7529
7530 EXIT();
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307531 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307532}
7533
7534#endif /*FEATURE_WLAN_SCAN_PNO*/
7535
7536
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007537#ifdef FEATURE_WLAN_TDLS
7538static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
7539 u8 *peer, u8 action_code, u8 dialog_token,
7540 u16 status_code, const u8 *buf, size_t len)
7541{
7542
7543 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7544 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007545 u8 peerMac[6];
7546 VOS_STATUS status;
Gopichand Nakkala05922802013-03-14 12:23:19 -07007547 int max_sta_failed = 0;
Hoonki Leea34dd892013-02-05 22:56:02 -08007548 int responder;
Hoonki Leed37cbb32013-04-20 00:31:14 -07007549 long rc;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007550
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007551 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007552 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307553 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007554 "Invalid arguments");
7555 return -EINVAL;
7556 }
7557
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08007558 if (pHddCtx->isLogpInProgress)
7559 {
7560 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7561 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07007562 wlan_hdd_tdls_set_link_status(pAdapter, peer, eTDLS_LINK_IDLE);
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08007563 return -EBUSY;
7564 }
7565
Hoonki Lee27511902013-03-14 18:19:06 -07007566 if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007567 {
Hoonki Lee27511902013-03-14 18:19:06 -07007568 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
7569 "%s: TDLS mode is disabled OR not enabled in FW."
7570 MAC_ADDRESS_STR " action %d declined.",
7571 __func__, MAC_ADDR_ARRAY(peer), action_code);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007572 return -ENOTSUPP;
7573 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08007574
Hoonki Lee27511902013-03-14 18:19:06 -07007575 /* other than teardown frame, other mgmt frames are not sent if disabled */
7576 if (SIR_MAC_TDLS_TEARDOWN != action_code)
7577 {
7578 /* if tdls_mode is disabled to respond to peer's request */
7579 if (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode)
7580 {
7581 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
7582 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07007583 " TDLS mode is disabled. action %d declined.",
7584 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee27511902013-03-14 18:19:06 -07007585
7586 return -ENOTSUPP;
7587 }
7588 }
7589
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007590 if (WLAN_IS_TDLS_SETUP_ACTION(action_code))
7591 {
Hoonki Leefb8df672013-04-10 18:20:34 -07007592 if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, peer, TRUE, TRUE))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007593 {
7594 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007595 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07007596 " TDLS setup is ongoing. action %d declined.",
7597 __func__, MAC_ADDR_ARRAY(peer), action_code);
7598 return -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007599 }
7600 }
7601
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007602 if (SIR_MAC_TDLS_SETUP_REQ == action_code ||
7603 SIR_MAC_TDLS_SETUP_RSP == action_code )
Lee Hoonkic1262f22013-01-24 21:59:00 -08007604 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007605 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
Lee Hoonkic1262f22013-01-24 21:59:00 -08007606 {
7607 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
7608 we return error code at 'add_station()'. Hence we have this
7609 check again in addtion to add_station().
7610 Anyway, there is no hard to double-check. */
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007611 if (SIR_MAC_TDLS_SETUP_REQ == action_code)
Lee Hoonkic1262f22013-01-24 21:59:00 -08007612 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007613 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7614 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07007615 " TDLS Max peer already connected. action %d declined.",
7616 __func__, MAC_ADDR_ARRAY(peer), action_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07007617 goto error;
Lee Hoonkic1262f22013-01-24 21:59:00 -08007618 }
7619 else
7620 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007621 /* maximum reached. tweak to send error code to peer and return
7622 error code to supplicant */
Lee Hoonkic1262f22013-01-24 21:59:00 -08007623 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007624 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7625 "%s: " MAC_ADDRESS_STR
7626 " TDLS Max peer already connected send response status %d",
7627 __func__, MAC_ADDR_ARRAY(peer), status_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07007628 max_sta_failed = -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007629 /* fall through to send setup resp with failure status
7630 code */
Lee Hoonkic1262f22013-01-24 21:59:00 -08007631 }
7632 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007633 else
7634 {
7635 hddTdlsPeer_t *pTdlsPeer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007636 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007637 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007638 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007639 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07007640 "%s:" MAC_ADDRESS_STR " already connected. action %d declined.",
7641 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007642 return -EPERM;
7643 }
7644 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08007645 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007646 vos_mem_copy(peerMac, peer, 6);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007647
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007648#ifdef WLAN_FEATURE_TDLS_DEBUG
7649 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007650 "%s: " MAC_ADDRESS_STR " action %d, dialog_token %d status %d, len = %d",
7651 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
7652 action_code, dialog_token, status_code, len);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007653#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007654
Hoonki Leea34dd892013-02-05 22:56:02 -08007655 /*Except teardown responder will not be used so just make 0*/
7656 responder = 0;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007657 if (SIR_MAC_TDLS_TEARDOWN == action_code)
Hoonki Leea34dd892013-02-05 22:56:02 -08007658 {
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -07007659
7660 hddTdlsPeer_t *pTdlsPeer;
7661 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peerMac);
7662
7663 if(pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
7664 responder = pTdlsPeer->is_responder;
7665 else
Hoonki Leea34dd892013-02-05 22:56:02 -08007666 {
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -07007667 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7668 "%s: " MAC_ADDRESS_STR " peer doesn't exist or not connected %d dialog_token %d status %d, len = %d",
7669 __func__, MAC_ADDR_ARRAY(peer), (NULL == pTdlsPeer) ? -1 : pTdlsPeer->link_status,
7670 dialog_token, status_code, len);
7671 return -EPERM;
Hoonki Leea34dd892013-02-05 22:56:02 -08007672 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007673 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007674
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05307675 /* For explicit trigger of DIS_REQ come out of BMPS for
7676 successfully receiving DIS_RSP from peer. */
Hoonki Lee14621352013-04-16 17:51:19 -07007677 if ((SIR_MAC_TDLS_SETUP_RSP == action_code) ||
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05307678 (SIR_MAC_TDLS_DIS_RSP == action_code) ||
7679 (SIR_MAC_TDLS_DIS_REQ == action_code))
Hoonki Lee14621352013-04-16 17:51:19 -07007680 {
7681 if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter)))
7682 {
7683 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05307684 "%s: Sending frame action_code %u.Disable BMPS", __func__, action_code);
Hoonki Lee14621352013-04-16 17:51:19 -07007685 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
7686 }
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05307687 if (SIR_MAC_TDLS_DIS_REQ != action_code)
7688 wlan_hdd_tdls_set_cap(pAdapter, peerMac, eTDLS_CAP_SUPPORTED);
Hoonki Lee14621352013-04-16 17:51:19 -07007689 }
7690
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007691 /* make sure doesn't call send_mgmt() while it is pending */
7692 if (TDLS_CTX_MAGIC == pAdapter->mgmtTxCompletionStatus)
7693 {
7694 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7695 "%s: " MAC_ADDRESS_STR " action %d couldn't sent, as one is pending. return EBUSY\n",
7696 __func__, MAC_ADDR_ARRAY(peer), action_code);
7697 return -EBUSY;
7698 }
7699
7700 pAdapter->mgmtTxCompletionStatus = TDLS_CTX_MAGIC;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007701 INIT_COMPLETION(pAdapter->tdls_mgmt_comp);
7702
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007703 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
Hoonki Leea34dd892013-02-05 22:56:02 -08007704 peerMac, action_code, dialog_token, status_code, (tANI_U8 *)buf, len, responder);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007705
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007706 if (VOS_STATUS_SUCCESS != status)
7707 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007708 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7709 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007710 pAdapter->mgmtTxCompletionStatus = FALSE;
Hoonki Lee14621352013-04-16 17:51:19 -07007711 wlan_hdd_tdls_check_bmps(pAdapter);
7712 goto error;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007713 }
7714
Hoonki Leed37cbb32013-04-20 00:31:14 -07007715 rc = wait_for_completion_interruptible_timeout(&pAdapter->tdls_mgmt_comp,
7716 msecs_to_jiffies(WAIT_TIME_TDLS_MGMT));
7717
7718 if ((rc <= 0) || (TRUE != pAdapter->mgmtTxCompletionStatus))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007719 {
Hoonki Leed37cbb32013-04-20 00:31:14 -07007720 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7721 "%s: Mgmt Tx Completion failed status %ld TxCompletion %lu",
7722 __func__, rc, pAdapter->mgmtTxCompletionStatus);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007723 pAdapter->mgmtTxCompletionStatus = FALSE;
Hoonki Leed37cbb32013-04-20 00:31:14 -07007724 wlan_hdd_tdls_check_bmps(pAdapter);
7725 goto error;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007726 }
7727
Gopichand Nakkala05922802013-03-14 12:23:19 -07007728 if (max_sta_failed)
Hoonki Lee14621352013-04-16 17:51:19 -07007729 {
7730 wlan_hdd_tdls_check_bmps(pAdapter);
Gopichand Nakkala05922802013-03-14 12:23:19 -07007731 return max_sta_failed;
Hoonki Lee14621352013-04-16 17:51:19 -07007732 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007733
Hoonki Leea34dd892013-02-05 22:56:02 -08007734 if (SIR_MAC_TDLS_SETUP_RSP == action_code)
7735 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007736 wlan_hdd_tdls_set_responder(pAdapter, peerMac, TRUE);
Hoonki Leea34dd892013-02-05 22:56:02 -08007737 }
7738 else if (SIR_MAC_TDLS_SETUP_CNF == action_code)
7739 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007740 wlan_hdd_tdls_set_responder(pAdapter, peerMac, FALSE);
Hoonki Leea34dd892013-02-05 22:56:02 -08007741 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007742
7743 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07007744error:
7745 /* max_sta_failed ; we didn't set to CONNECTING for this case,
7746 because we already know that this transaction will be failed,
7747 but we weren't sure if supplicant call DISABLE_LINK or not. So,
7748 to be safe, do not change the state mahine.
7749 */
7750 if(max_sta_failed == 0 &&
7751 (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
7752 wlan_hdd_tdls_set_link_status(pAdapter, peerMac, eTDLS_LINK_IDLE);
7753 return -EPERM;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007754}
7755
7756static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
7757 u8 *peer, enum nl80211_tdls_operation oper)
7758{
7759 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7760 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307761 int status;
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007762#ifdef WLAN_FEATURE_TDLS_DEBUG
7763 const char *tdls_oper_str[]= {
7764 "NL80211_TDLS_DISCOVERY_REQ",
7765 "NL80211_TDLS_SETUP",
7766 "NL80211_TDLS_TEARDOWN",
7767 "NL80211_TDLS_ENABLE_LINK",
7768 "NL80211_TDLS_DISABLE_LINK",
Gopichand Nakkala29d00192013-06-20 19:03:52 +05307769 "NL80211_TDLS_UNKNOWN_OPER"};
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007770#endif
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007771 hddTdlsPeer_t *pTdlsPeer;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007772
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307773 if ( NULL == peer )
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007774 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007775 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Chilam Ngc4244af2013-04-01 15:37:32 -07007776 "%s: Invalid arguments", __func__);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007777 return -EINVAL;
7778 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007779
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307780 status = wlan_hdd_validate_context(pHddCtx);
7781
7782 if (0 != status)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08007783 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307784 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7785 "%s: HDD context is not valid", __func__);
7786 return status;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08007787 }
7788
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007789 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
7790
7791 if ( NULL == pTdlsPeer ) {
7792 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: " MAC_ADDRESS_STR " (oper %d) not exsting. ignored",
7793 __func__, MAC_ADDR_ARRAY(peer), (int)oper);
7794 return -EINVAL;
7795 }
7796
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007797#ifdef WLAN_FEATURE_TDLS_DEBUG
7798 if((int)oper > 4)
7799 oper = 5;
7800
7801 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007802 "%s: " MAC_ADDRESS_STR " link_status %d (%s) ", "tdls_oper",
7803 MAC_ADDR_ARRAY(peer), pTdlsPeer->link_status,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007804 tdls_oper_str[(int)oper]);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007805#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007806
7807 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007808 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007809 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007810 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Chilam Ngc4244af2013-04-01 15:37:32 -07007811 "TDLS Disabled in INI OR not enabled in FW. "
7812 "Cannot process TDLS commands");
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007813 return -ENOTSUPP;
7814 }
7815
7816 switch (oper) {
7817 case NL80211_TDLS_ENABLE_LINK:
7818 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007819 VOS_STATUS status;
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307820 tCsrTdlsLinkEstablishParams tdlsLinkEstablishParams;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007821
Gopichand Nakkala2f4a2822013-04-17 11:22:01 -07007822 if (!TDLS_STA_INDEX_VALID(pTdlsPeer->staId))
7823 {
7824 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Staion Index %u "
7825 MAC_ADDRESS_STR " failed",
7826 __func__, pTdlsPeer->staId, MAC_ADDR_ARRAY(peer));
7827 return -EINVAL;
7828 }
7829
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007830 if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status)
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007831 {
Gopichand Nakkala24be5312013-07-02 16:47:12 +05307832 long ret;
7833
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307834 if (0 != wlan_hdd_tdls_get_link_establish_params(pAdapter, peer,&tdlsLinkEstablishParams)) {
7835 return -EINVAL;
7836 }
7837 INIT_COMPLETION(pAdapter->tdls_link_establish_req_comp);
7838
7839 sme_SendTdlsLinkEstablishParams(WLAN_HDD_GET_HAL_CTX(pAdapter),
7840 pAdapter->sessionId, peer, &tdlsLinkEstablishParams);
7841 /* Send TDLS peer UAPSD capabilities to the firmware and
7842 * register with the TL on after the response for this operation
7843 * is received .
7844 */
Gopichand Nakkala24be5312013-07-02 16:47:12 +05307845 ret = wait_for_completion_interruptible_timeout(&pAdapter->tdls_link_establish_req_comp,
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307846 msecs_to_jiffies(WAIT_TIME_TDLS_LINK_ESTABLISH_REQ));
Gopichand Nakkala24be5312013-07-02 16:47:12 +05307847 if (ret <= 0)
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307848 {
7849 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7850 "%s: Link Establish Request Faled Status %ld",
Gopichand Nakkala24be5312013-07-02 16:47:12 +05307851 __func__, ret);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307852 return -EINVAL;
7853 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007854 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
Gopichand Nakkala471708b2013-06-04 20:03:01 +05307855 /* Mark TDLS client Authenticated .*/
7856 status = WLANTL_ChangeSTAState( pHddCtx->pvosContext,
7857 pTdlsPeer->staId,
7858 WLANTL_STA_AUTHENTICATED);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007859 if (VOS_STATUS_SUCCESS == status)
7860 {
Hoonki Lee14621352013-04-16 17:51:19 -07007861 if (pTdlsPeer->is_responder == 0)
7862 {
7863 v_U8_t staId = (v_U8_t)pTdlsPeer->staId;
7864
7865 wlan_hdd_tdls_timer_restart(pAdapter,
7866 &pTdlsPeer->initiatorWaitTimeoutTimer,
7867 WAIT_TIME_TDLS_INITIATOR);
7868 /* suspend initiator TX until it receives direct packet from the
7869 reponder or WAIT_TIME_TDLS_INITIATOR timer expires */
7870 WLANTL_SuspendDataTx( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
7871 &staId, NULL);
7872 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007873 wlan_hdd_tdls_increment_peer_count(pAdapter);
7874 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007875 wlan_hdd_tdls_check_bmps(pAdapter);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307876
7877 /* Update TL about the UAPSD masks , to route the packets to firmware */
Gopichand Nakkala574f6d12013-06-27 19:38:43 +05307878 if ((TRUE == pHddCtx->cfg_ini->fEnableTDLSBufferSta)
7879 || pHddCtx->cfg_ini->fTDLSUapsdMask )
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307880 {
Gopichand Nakkala574f6d12013-06-27 19:38:43 +05307881 int ac;
7882 uint8 ucAc[4] = { WLANTL_AC_VO,
7883 WLANTL_AC_VI,
7884 WLANTL_AC_BK,
7885 WLANTL_AC_BE };
7886 uint8 tlTid[4] = { 7, 5, 2, 3 } ;
7887 for(ac=0; ac < 4; ac++)
7888 {
7889 status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
7890 pTdlsPeer->staId, ucAc[ac],
7891 tlTid[ac], tlTid[ac], 0, 0,
7892 WLANTL_BI_DIR );
7893 }
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307894 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007895 }
7896
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007897 }
7898 break;
7899 case NL80211_TDLS_DISABLE_LINK:
Lee Hoonkic1262f22013-01-24 21:59:00 -08007900 {
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007901 if(TDLS_STA_INDEX_VALID(pTdlsPeer->staId))
Lee Hoonkic1262f22013-01-24 21:59:00 -08007902 {
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007903 long status;
7904
7905 INIT_COMPLETION(pAdapter->tdls_del_station_comp);
7906
Lee Hoonkic1262f22013-01-24 21:59:00 -08007907 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
7908 pAdapter->sessionId, peer );
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007909
7910 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_del_station_comp,
7911 msecs_to_jiffies(WAIT_TIME_TDLS_DEL_STA));
7912 if (status <= 0)
7913 {
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007914 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_IDLE);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007915 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7916 "%s: Del station failed status %ld",
7917 __func__, status);
7918 return -EPERM;
7919 }
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007920 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_IDLE);
Lee Hoonkic1262f22013-01-24 21:59:00 -08007921 }
7922 else
7923 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007924 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7925 "%s: TDLS Peer Station doesn't exist.", __func__);
Lee Hoonkic1262f22013-01-24 21:59:00 -08007926 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08007927 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007928 break;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007929 case NL80211_TDLS_TEARDOWN:
7930 case NL80211_TDLS_SETUP:
7931 case NL80211_TDLS_DISCOVERY_REQ:
7932 /* We don't support in-driver setup/teardown/discovery */
7933 return -ENOTSUPP;
7934 default:
7935 return -ENOTSUPP;
7936 }
7937 return 0;
7938}
Chilam NG571c65a2013-01-19 12:27:36 +05307939
7940int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
7941 struct net_device *dev, u8 *peer)
7942{
7943 hddLog(VOS_TRACE_LEVEL_INFO, "tdls send discover req: %x %x %x %x %x %x",
7944 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5]);
7945
7946 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
7947 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
7948}
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007949#endif
7950
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05307951#ifdef WLAN_FEATURE_GTK_OFFLOAD
7952/*
7953 * FUNCTION: wlan_hdd_cfg80211_update_replayCounterCallback
7954 * Callback rountine called upon receiving response for
7955 * get offload info
7956 */
7957void wlan_hdd_cfg80211_update_replayCounterCallback(void *callbackContext,
7958 tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoRsp)
7959{
7960
7961 hdd_adapter_t *pAdapter = (hdd_adapter_t *)callbackContext;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05307962 tANI_U8 tempReplayCounter[8];
7963 hdd_station_ctx_t *pHddStaCtx;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05307964
7965 ENTER();
7966
7967 if (NULL == pAdapter)
7968 {
7969 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7970 "%s: HDD adapter is Null", __func__);
7971 return ;
7972 }
7973
7974 if (NULL == pGtkOffloadGetInfoRsp)
7975 {
7976 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7977 "%s: pGtkOffloadGetInfoRsp is Null", __func__);
7978 return ;
7979 }
7980
7981 if (VOS_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus)
7982 {
7983 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7984 "%s: wlan Failed to get replay counter value",
7985 __func__);
7986 return ;
7987 }
7988
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05307989 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7990 /* Update replay counter */
7991 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
7992 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
7993
7994 {
7995 /* changing from little to big endian since supplicant
7996 * works on big endian format
7997 */
7998 int i;
7999 tANI_U8 *p = (tANI_U8 *)&pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
8000
8001 for (i = 0; i < 8; i++)
8002 {
8003 tempReplayCounter[7-i] = (tANI_U8)p[i];
8004 }
8005 }
8006
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308007 /* Update replay counter to NL */
8008 cfg80211_gtk_rekey_notify(pAdapter->dev, pGtkOffloadGetInfoRsp->bssId,
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308009 tempReplayCounter, GFP_KERNEL);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308010}
8011
8012/*
8013 * FUNCTION: wlan_hdd_cfg80211_set_rekey_data
8014 * This function is used to offload GTK rekeying job to the firmware.
8015 */
8016int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
8017 struct cfg80211_gtk_rekey_data *data)
8018{
8019 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8020 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8021 hdd_station_ctx_t *pHddStaCtx;
8022 tHalHandle hHal;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308023 int result;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308024 tSirGtkOffloadParams hddGtkOffloadReqParams;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308025 eHalStatus status = eHAL_STATUS_FAILURE;
8026
8027 ENTER();
8028
8029 if (NULL == pAdapter)
8030 {
8031 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8032 "%s: HDD adapter is Null", __func__);
8033 return -ENODEV;
8034 }
8035
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308036 result = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308037
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308038 if (0 != result)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308039 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308040 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8041 "%s: HDD context is not valid", __func__);
8042 return result;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308043 }
8044
8045 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8046 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8047 if (NULL == hHal)
8048 {
8049 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8050 "%s: HAL context is Null!!!", __func__);
8051 return -EAGAIN;
8052 }
8053
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308054 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
8055 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck, NL80211_KCK_LEN);
8056 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek, NL80211_KEK_LEN);
8057 memcpy(pHddStaCtx->gtkOffloadReqParams.bssId, &pHddStaCtx->conn_info.bssId,
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308058 WNI_CFG_BSSID_LEN);
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308059 {
8060 /* changing from big to little endian since driver
8061 * works on little endian format
8062 */
8063 tANI_U8 *p =
8064 (tANI_U8 *)&pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter;
8065 int i;
8066
8067 for (i = 0; i < 8; i++)
8068 {
8069 p[7-i] = data->replay_ctr[i];
8070 }
8071 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308072
8073 if (TRUE == pHddCtx->hdd_wlan_suspended)
8074 {
8075 /* if wlan is suspended, enable GTK offload directly from here */
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308076 memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams,
8077 sizeof (tSirGtkOffloadParams));
8078 status = sme_SetGTKOffload(hHal, &hddGtkOffloadReqParams,
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308079 pAdapter->sessionId);
8080
8081 if (eHAL_STATUS_SUCCESS != status)
8082 {
8083 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8084 "%s: sme_SetGTKOffload failed, returned %d",
8085 __func__, status);
8086 return status;
8087 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308088 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8089 "%s: sme_SetGTKOffload successfull", __func__);
8090 }
8091 else
8092 {
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308093 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8094 "%s: wlan not suspended GTKOffload request is stored",
8095 __func__);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308096 }
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308097
8098 return eHAL_STATUS_SUCCESS;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308099}
8100#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
8101
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05308102/*
8103 * FUNCTION: wlan_hdd_cfg80211_set_mac_acl
8104 * This function is used to set access control policy
8105 */
8106static int wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
8107 struct net_device *dev, const struct cfg80211_acl_data *params)
8108{
8109 int i;
8110 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8111 hdd_hostapd_state_t *pHostapdState;
8112 tsap_Config_t *pConfig;
8113 v_CONTEXT_t pVosContext = NULL;
8114 hdd_context_t *pHddCtx;
8115 int status;
8116
8117 ENTER();
8118
8119 if (NULL == pAdapter)
8120 {
8121 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8122 "%s: HDD adapter is Null", __func__);
8123 return -ENODEV;
8124 }
8125
8126 if (NULL == params)
8127 {
8128 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8129 "%s: params is Null", __func__);
8130 return -EINVAL;
8131 }
8132
8133 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8134 status = wlan_hdd_validate_context(pHddCtx);
8135
8136 if (0 != status)
8137 {
8138 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8139 "%s: HDD context is not valid", __func__);
8140 return status;
8141 }
8142
8143 pVosContext = pHddCtx->pvosContext;
8144 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
8145
8146 if (NULL == pHostapdState)
8147 {
8148 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8149 "%s: pHostapdState is Null", __func__);
8150 return -EINVAL;
8151 }
8152
8153 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"acl policy: = %d"
8154 "no acl entries = %d", params->acl_policy, params->n_acl_entries);
8155
8156 if (WLAN_HDD_SOFTAP == pAdapter->device_mode)
8157 {
8158 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
8159
8160 /* default value */
8161 pConfig->num_accept_mac = 0;
8162 pConfig->num_deny_mac = 0;
8163
8164 /**
8165 * access control policy
8166 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
8167 * listed in hostapd.deny file.
8168 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
8169 * listed in hostapd.accept file.
8170 */
8171 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy)
8172 {
8173 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
8174 }
8175 else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED == params->acl_policy)
8176 {
8177 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
8178 }
8179 else
8180 {
8181 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8182 "%s:Acl Policy : %d is not supported",
8183 __func__, params->acl_policy);
8184 return -ENOTSUPP;
8185 }
8186
8187 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl)
8188 {
8189 pConfig->num_accept_mac = params->n_acl_entries;
8190 for (i = 0; i < params->n_acl_entries; i++)
8191 {
8192 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8193 "** Add ACL MAC entry %i in WhiletList :"
8194 MAC_ADDRESS_STR, i,
8195 MAC_ADDR_ARRAY(params->mac_addrs[i].addr));
8196
8197 vos_mem_copy(&pConfig->accept_mac[i], params->mac_addrs[i].addr,
8198 sizeof(qcmacaddr));
8199 }
8200 }
8201 else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl)
8202 {
8203 pConfig->num_deny_mac = params->n_acl_entries;
8204 for (i = 0; i < params->n_acl_entries; i++)
8205 {
8206 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8207 "** Add ACL MAC entry %i in BlackList :"
8208 MAC_ADDRESS_STR, i,
8209 MAC_ADDR_ARRAY(params->mac_addrs[i].addr));
8210
8211 vos_mem_copy(&pConfig->deny_mac[i], params->mac_addrs[i].addr,
8212 sizeof(qcmacaddr));
8213 }
8214 }
8215
8216 if (VOS_STATUS_SUCCESS != WLANSAP_SetMacACL(pVosContext, pConfig))
8217 {
8218 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8219 "%s: SAP Set Mac Acl fail", __func__);
8220 return -EINVAL;
8221 }
8222 }
8223 else
8224 {
8225 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8226 "%s: Invalid device_mode = %d",
8227 __func__, pAdapter->device_mode);
8228 return -EINVAL;
8229 }
8230
8231 return 0;
8232}
8233
Leo Chang9056f462013-08-01 19:21:11 -07008234#ifdef WLAN_NL80211_TESTMODE
8235#ifdef FEATURE_WLAN_LPHB
8236static void wlan_hdd_cfg80211_lphb_wait_timeout_ind_handler
8237(
8238 void *pAdapter,
8239 void *indCont
8240)
8241{
8242 tSirLPHBTimeoutInd *lphbTimeoutInd;
8243 struct sk_buff *skb;
8244
8245 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8246 "LPHB wait timeout indication arrived");
8247
8248 if (NULL == indCont)
8249 {
8250 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8251 "LPHB timeout, invalid argument");
8252 return;
8253 }
8254
8255 lphbTimeoutInd = (tSirLPHBTimeoutInd *)indCont;
8256 skb = cfg80211_testmode_alloc_event_skb(
8257 ((hdd_adapter_t *)pAdapter)->wdev.wiphy,
8258 sizeof(tSirLPHBTimeoutInd),
8259 GFP_ATOMIC);
8260 if (!skb)
8261 {
8262 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8263 "LPHB timeout, NL buffer alloc fail");
8264 return;
8265 }
8266
8267 NLA_PUT_U32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB);
8268 NLA_PUT_U32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbTimeoutInd->protocolType);
8269 NLA_PUT(skb, WLAN_HDD_TM_ATTR_DATA,
8270 sizeof(tSirLPHBTimeoutInd), lphbTimeoutInd);
8271 cfg80211_testmode_event(skb, GFP_ATOMIC);
8272 return;
8273
8274nla_put_failure:
8275 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8276 "NLA Put fail");
8277 kfree_skb(skb);
8278
8279 return;
8280}
8281#endif /* FEATURE_WLAN_LPHB */
8282
8283static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy, void *data, int len)
8284{
8285 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
8286 int err = 0;
8287#ifdef FEATURE_WLAN_LPHB
8288 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8289#endif /* FEATURE_WLAN_LPHB */
8290
8291 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data, len, wlan_hdd_tm_policy);
8292 if (err)
8293 {
8294 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8295 "%s Testmode INV ATTR", __func__);
8296 return err;
8297 }
8298
8299 if (!tb[WLAN_HDD_TM_ATTR_CMD])
8300 {
8301 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8302 "%s Testmode INV CMD", __func__);
8303 return -EINVAL;
8304 }
8305
8306 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]))
8307 {
8308#ifdef FEATURE_WLAN_LPHB
8309 /* Low Power Heartbeat configuration request */
8310 case WLAN_HDD_TM_CMD_WLAN_HB:
8311 {
8312 int buf_len;
8313 void *buf;
8314 tSirLPHBReq *hb_params = NULL;
8315
8316 if (!tb[WLAN_HDD_TM_ATTR_DATA])
8317 {
8318 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8319 "%s Testmode INV DATA", __func__);
8320 return -EINVAL;
8321 }
8322
8323 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
8324 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
8325 hb_params = (tSirLPHBReq *)vos_mem_malloc(sizeof(tSirLPHBReq));
8326 if (NULL == hb_params)
8327 {
8328 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8329 "%s Request Buffer Alloc Fail", __func__);
8330 return -EINVAL;
8331 }
8332
8333 vos_mem_copy(hb_params, buf, buf_len);
8334
8335 /* LPHB enable and disable request will send to FW
8336 * when host suspend and resume
8337 * host suspend -> enable LPHB
8338 * host resume -> disable LPHB
8339 * if host is not suspend, cache into HDD context
8340 * and when host goes to suspend, send request to FW */
8341 if ((LPHB_SET_EN_PARAMS_INDID == hb_params->cmd) &&
8342 (!pHddCtx->hdd_wlan_suspended))
8343 {
8344 /* Feature enable command cache into HDD context,
8345 * if WLAN is not suspend
8346 * When WLAN goes into suspend, send enable command to FW */
8347 pHddCtx->lphbEnableReq.enable =
8348 hb_params->params.lphbEnableReq.enable;
8349 pHddCtx->lphbEnableReq.item =
8350 hb_params->params.lphbEnableReq.item;
8351 pHddCtx->lphbEnableReq.session =
8352 hb_params->params.lphbEnableReq.session;
8353 vos_mem_free(hb_params);
8354 }
8355 else
8356 {
8357 eHalStatus smeStatus;
8358
8359 /* If WLAN is suspend state, send enable command immediately */
8360 smeStatus = sme_LPHBConfigReq((tHalHandle)(pHddCtx->hHal),
8361 hb_params,
8362 wlan_hdd_cfg80211_lphb_wait_timeout_ind_handler);
8363 if (eHAL_STATUS_SUCCESS != smeStatus)
8364 {
8365 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8366 "LPHB Config Fail, disable");
8367 pHddCtx->lphbEnableReq.enable = 0;
8368 vos_mem_free(hb_params);
8369 }
8370 }
8371 return 0;
8372 }
8373#endif /* FEATURE_WLAN_LPHB */
8374 default:
8375 return -EOPNOTSUPP;
8376 }
8377
8378 return err;
8379}
8380#endif /* CONFIG_NL80211_TESTMODE */
8381
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308382static int wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy,
8383 struct net_device *dev,
8384 int idx, struct survey_info *survey)
8385{
8386 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8387 hdd_context_t *pHddCtx;
Mihir Sheted9072e02013-08-21 17:02:29 +05308388 hdd_station_ctx_t *pHddStaCtx;
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308389 tHalHandle halHandle;
Mihir Sheted9072e02013-08-21 17:02:29 +05308390 v_U32_t channel = 0, freq = 0; /* Initialization Required */
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308391 v_S7_t snr,rssi;
8392 int status, i, j, filled = 0;
8393
8394 ENTER();
8395
8396
8397 if (NULL == pAdapter)
8398 {
8399 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8400 "%s: HDD adapter is Null", __func__);
8401 return -ENODEV;
8402 }
8403
8404 if (NULL == wiphy)
8405 {
8406 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8407 "%s: wiphy is Null", __func__);
8408 return -ENODEV;
8409 }
8410
8411 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8412 status = wlan_hdd_validate_context(pHddCtx);
8413
8414 if (0 != status)
8415 {
8416 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8417 "%s: HDD context is not valid", __func__);
8418 return status;
8419 }
8420
Mihir Sheted9072e02013-08-21 17:02:29 +05308421 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8422
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308423 if (0 == pHddCtx->cfg_ini->fEnableSNRMonitoring ||
Mihir Sheted9072e02013-08-21 17:02:29 +05308424 0 != pAdapter->survey_idx ||
8425 eConnectionState_Associated != pHddStaCtx->conn_info.connState)
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308426 {
8427 /* The survey dump ops when implemented completely is expected to
8428 * return a survey of all channels and the ops is called by the
8429 * kernel with incremental values of the argument 'idx' till it
8430 * returns -ENONET. But we can only support the survey for the
8431 * operating channel for now. survey_idx is used to track
8432 * that the ops is called only once and then return -ENONET for
8433 * the next iteration
8434 */
8435 pAdapter->survey_idx = 0;
8436 return -ENONET;
8437 }
8438
8439 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
8440
8441 wlan_hdd_get_snr(pAdapter, &snr);
8442 wlan_hdd_get_rssi(pAdapter, &rssi);
8443
8444 sme_GetOperationChannel(halHandle, &channel, pAdapter->sessionId);
8445 hdd_wlan_get_freq(channel, &freq);
8446
8447
8448 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
8449 {
8450 if (NULL == wiphy->bands[i])
8451 {
8452 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
8453 "%s: wiphy->bands[i] is NULL, i = %d", __func__, i);
8454 continue;
8455 }
8456
8457 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
8458 {
8459 struct ieee80211_supported_band *band = wiphy->bands[i];
8460
8461 if (band->channels[j].center_freq == (v_U16_t)freq)
8462 {
8463 survey->channel = &band->channels[j];
8464 /* The Rx BDs contain SNR values in dB for the received frames
8465 * while the supplicant expects noise. So we calculate and
8466 * return the value of noise (dBm)
8467 * SNR (dB) = RSSI (dBm) - NOISE (dBm)
8468 */
8469 survey->noise = rssi - snr;
8470 survey->filled = SURVEY_INFO_NOISE_DBM;
8471 filled = 1;
8472 }
8473 }
8474 }
8475
8476 if (filled)
8477 pAdapter->survey_idx = 1;
8478 else
8479 {
8480 pAdapter->survey_idx = 0;
8481 return -ENONET;
8482 }
8483
8484 return 0;
8485}
8486
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308487/*
8488 * FUNCTION: wlan_hdd_cfg80211_resume_wlan
8489 * this is called when cfg80211 driver resume
8490 * driver updates latest sched_scan scan result(if any) to cfg80211 database
8491 */
8492int wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
8493{
8494 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8495 hdd_adapter_t *pAdapter;
8496 hdd_adapter_list_node_t *pAdapterNode, *pNext;
8497 VOS_STATUS status = VOS_STATUS_SUCCESS;
8498
8499 ENTER();
8500
8501 if ( NULL == pHddCtx )
8502 {
8503 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8504 "%s: HddCtx validation failed", __func__);
8505 return 0;
8506 }
8507
8508 if (pHddCtx->isLogpInProgress)
8509 {
8510 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8511 "%s: LOGP in Progress. Ignore!!!", __func__);
8512 return 0;
8513 }
8514
8515 if (pHddCtx->isLoadUnloadInProgress)
8516 {
8517 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8518 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
8519 return 0;
8520 }
8521
8522 spin_lock(&pHddCtx->schedScan_lock);
8523 pHddCtx->isWiphySuspended = FALSE;
8524 if (TRUE != pHddCtx->isSchedScanUpdatePending)
8525 {
8526 spin_unlock(&pHddCtx->schedScan_lock);
8527 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8528 "%s: Return resume is not due to PNO indication", __func__);
8529 return 0;
8530 }
8531 // Reset flag to avoid updatating cfg80211 data old results again
8532 pHddCtx->isSchedScanUpdatePending = FALSE;
8533 spin_unlock(&pHddCtx->schedScan_lock);
8534
8535 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8536
8537 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
8538 {
8539 pAdapter = pAdapterNode->pAdapter;
8540 if ( (NULL != pAdapter) &&
8541 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
8542 {
8543 if (0 != wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter))
8544 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
8545 "%s: NO SCAN result", __func__);
8546 else
8547 cfg80211_sched_scan_results(pHddCtx->wiphy);
8548
8549 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8550 "%s : cfg80211 scan result database updated", __func__);
8551
8552 return 0;
8553
8554 }
8555 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8556 pAdapterNode = pNext;
8557 }
8558
8559 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8560 "%s: Failed to find Adapter", __func__);
8561 return 0;
8562}
8563
8564/*
8565 * FUNCTION: wlan_hdd_cfg80211_suspend_wlan
8566 * this is called when cfg80211 driver suspends
8567 */
8568int wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
8569 struct cfg80211_wowlan *wow)
8570{
8571 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8572
8573 ENTER();
8574 if (NULL == pHddCtx)
8575 {
8576 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8577 "%s: HddCtx validation failed", __func__);
8578 return 0;
8579 }
8580
8581 pHddCtx->isWiphySuspended = TRUE;
8582
8583 EXIT();
8584
8585 return 0;
8586}
8587
Jeff Johnson295189b2012-06-20 16:38:30 -07008588/* cfg80211_ops */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308589static struct cfg80211_ops wlan_hdd_cfg80211_ops =
Jeff Johnson295189b2012-06-20 16:38:30 -07008590{
8591 .add_virtual_intf = wlan_hdd_add_virtual_intf,
8592 .del_virtual_intf = wlan_hdd_del_virtual_intf,
8593 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
8594 .change_station = wlan_hdd_change_station,
8595#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
8596 .add_beacon = wlan_hdd_cfg80211_add_beacon,
8597 .del_beacon = wlan_hdd_cfg80211_del_beacon,
8598 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008599#else
8600 .start_ap = wlan_hdd_cfg80211_start_ap,
8601 .change_beacon = wlan_hdd_cfg80211_change_beacon,
8602 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07008603#endif
8604 .change_bss = wlan_hdd_cfg80211_change_bss,
8605 .add_key = wlan_hdd_cfg80211_add_key,
8606 .get_key = wlan_hdd_cfg80211_get_key,
8607 .del_key = wlan_hdd_cfg80211_del_key,
8608 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08008609#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07008610 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08008611#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008612 .scan = wlan_hdd_cfg80211_scan,
8613 .connect = wlan_hdd_cfg80211_connect,
8614 .disconnect = wlan_hdd_cfg80211_disconnect,
8615 .join_ibss = wlan_hdd_cfg80211_join_ibss,
8616 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
8617 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
8618 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
8619 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
Jeff Johnson295189b2012-06-20 16:38:30 -07008620 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
8621 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
8622 .mgmt_tx = wlan_hdd_action,
8623#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
8624 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
8625 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
8626 .set_txq_params = wlan_hdd_set_txq_params,
8627#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008628 .get_station = wlan_hdd_cfg80211_get_station,
8629 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
8630 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008631 .add_station = wlan_hdd_cfg80211_add_station,
8632#ifdef FEATURE_WLAN_LFR
8633 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
8634 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
8635 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
8636#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07008637#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
8638 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
8639#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008640#ifdef FEATURE_WLAN_TDLS
8641 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
8642 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
8643#endif
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308644#ifdef WLAN_FEATURE_GTK_OFFLOAD
8645 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
8646#endif /* WLAN_FEATURE_GTK_OFFLOAD */
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308647#ifdef FEATURE_WLAN_SCAN_PNO
8648 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
8649 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
8650#endif /*FEATURE_WLAN_SCAN_PNO */
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308651 .resume = wlan_hdd_cfg80211_resume_wlan,
8652 .suspend = wlan_hdd_cfg80211_suspend_wlan,
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05308653 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
Leo Chang9056f462013-08-01 19:21:11 -07008654#ifdef WLAN_NL80211_TESTMODE
8655 .testmode_cmd = wlan_hdd_cfg80211_testmode,
8656#endif
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308657 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Jeff Johnson295189b2012-06-20 16:38:30 -07008658};
8659