blob: a4a98d3d93d09701ce0e415171a57a7ffa199dca [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{
1196 v_U8_t ielen = 0;
1197 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
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001220#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001221static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1222 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001223#else
1224static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1225 struct cfg80211_beacon_data *params)
1226#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001227{
1228 v_U8_t *genie;
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301229 v_U8_t total_ielen = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001230 v_U8_t addIE[1] = {0};
Jeff Johnsone7245742012-09-05 17:12:55 -07001231 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001232
1233 genie = vos_mem_malloc(MAX_GENIE_LEN);
1234
1235 if(genie == NULL) {
1236
1237 return -ENOMEM;
1238 }
1239
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301240 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1241 &total_ielen, WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001242 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301243 ret = -EINVAL;
1244 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001245 }
1246
1247#ifdef WLAN_FEATURE_WFD
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301248 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1249 &total_ielen, WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE))
1250 {
1251 ret = -EINVAL;
1252 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001253 }
1254#endif
1255
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301256 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1257 &total_ielen, P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001258 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301259 ret = -EINVAL;
1260 goto done;
1261 }
1262
1263 if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode)
1264 {
1265 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1266 &total_ielen, SS_OUI_TYPE, SS_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001267 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301268 ret = -EINVAL;
1269 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001270 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001271 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001272
1273 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1274 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1275 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1276 {
1277 hddLog(LOGE,
1278 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001279 ret = -EINVAL;
1280 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001281 }
1282
1283 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1284 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1285 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1286 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1287 ==eHAL_STATUS_FAILURE)
1288 {
1289 hddLog(LOGE,
1290 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001291 ret = -EINVAL;
1292 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001293 }
1294
1295 // Added for ProResp IE
1296 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1297 {
1298 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1299 u8 probe_rsp_ie_len[3] = {0};
1300 u8 counter = 0;
1301 /* Check Probe Resp Length if it is greater then 255 then Store
1302 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1303 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1304 Store More then 255 bytes into One Variable.
1305 */
1306 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1307 {
1308 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1309 {
1310 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1311 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1312 }
1313 else
1314 {
1315 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1316 rem_probe_resp_ie_len = 0;
1317 }
1318 }
1319
1320 rem_probe_resp_ie_len = 0;
1321
1322 if (probe_rsp_ie_len[0] > 0)
1323 {
1324 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1325 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1326 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1327 probe_rsp_ie_len[0], NULL,
1328 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1329 {
1330 hddLog(LOGE,
1331 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001332 ret = -EINVAL;
1333 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001334 }
1335 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1336 }
1337
1338 if (probe_rsp_ie_len[1] > 0)
1339 {
1340 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1341 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1342 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1343 probe_rsp_ie_len[1], NULL,
1344 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1345 {
1346 hddLog(LOGE,
1347 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001348 ret = -EINVAL;
1349 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001350 }
1351 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1352 }
1353
1354 if (probe_rsp_ie_len[2] > 0)
1355 {
1356 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1357 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1358 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1359 probe_rsp_ie_len[2], NULL,
1360 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1361 {
1362 hddLog(LOGE,
1363 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001364 ret = -EINVAL;
1365 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001366 }
1367 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1368 }
1369
1370 if (probe_rsp_ie_len[1] == 0 )
1371 {
1372 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1373 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1374 eANI_BOOLEAN_FALSE) )
1375 {
1376 hddLog(LOGE,
1377 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1378 }
1379 }
1380
1381 if (probe_rsp_ie_len[2] == 0 )
1382 {
1383 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1384 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1385 eANI_BOOLEAN_FALSE) )
1386 {
1387 hddLog(LOGE,
1388 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1389 }
1390 }
1391
1392 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1393 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1394 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1395 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1396 == eHAL_STATUS_FAILURE)
1397 {
1398 hddLog(LOGE,
1399 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001400 ret = -EINVAL;
1401 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001402 }
1403 }
1404 else
1405 {
1406 // Reset WNI_CFG_PROBE_RSP Flags
1407 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1408
1409 hddLog(VOS_TRACE_LEVEL_INFO,
1410 "%s: No Probe Response IE received in set beacon",
1411 __func__);
1412 }
1413
1414 // Added for AssocResp IE
1415 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1416 {
1417 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1418 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1419 params->assocresp_ies_len, NULL,
1420 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1421 {
1422 hddLog(LOGE,
1423 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001424 ret = -EINVAL;
1425 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001426 }
1427
1428 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1429 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1430 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1431 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1432 == eHAL_STATUS_FAILURE)
1433 {
1434 hddLog(LOGE,
1435 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001436 ret = -EINVAL;
1437 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001438 }
1439 }
1440 else
1441 {
1442 hddLog(VOS_TRACE_LEVEL_INFO,
1443 "%s: No Assoc Response IE received in set beacon",
1444 __func__);
1445
1446 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1447 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1448 eANI_BOOLEAN_FALSE) )
1449 {
1450 hddLog(LOGE,
1451 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1452 }
1453 }
1454
Jeff Johnsone7245742012-09-05 17:12:55 -07001455done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001456 vos_mem_free(genie);
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301457 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07001458}
Jeff Johnson295189b2012-06-20 16:38:30 -07001459
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301460/*
Jeff Johnson295189b2012-06-20 16:38:30 -07001461 * FUNCTION: wlan_hdd_validate_operation_channel
1462 * called by wlan_hdd_cfg80211_start_bss() and
1463 * wlan_hdd_cfg80211_set_channel()
1464 * This function validates whether given channel is part of valid
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301465 * channel list.
1466 */
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001467VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001468{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301469
Jeff Johnson295189b2012-06-20 16:38:30 -07001470 v_U32_t num_ch = 0;
1471 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1472 u32 indx = 0;
1473 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301474 v_U8_t fValidChannel = FALSE, count = 0;
1475 hdd_config_t *hdd_pConfig_ini= (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301476
Jeff Johnson295189b2012-06-20 16:38:30 -07001477 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1478
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301479 if ( hdd_pConfig_ini->sapAllowAllChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001480 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301481 /* Validate the channel */
1482 for (count = RF_CHAN_1 ; count <= RF_CHAN_165 ; count++)
Jeff Johnson295189b2012-06-20 16:38:30 -07001483 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301484 if ( channel == rfChannels[count].channelNum )
1485 {
1486 fValidChannel = TRUE;
1487 break;
1488 }
1489 }
1490 if (fValidChannel != TRUE)
1491 {
1492 hddLog(VOS_TRACE_LEVEL_ERROR,
1493 "%s: Invalid Channel [%d]", __func__, channel);
1494 return VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001495 }
1496 }
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301497 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001498 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301499 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1500 valid_ch, &num_ch))
1501 {
1502 hddLog(VOS_TRACE_LEVEL_ERROR,
1503 "%s: failed to get valid channel list", __func__);
1504 return VOS_STATUS_E_FAILURE;
1505 }
1506 for (indx = 0; indx < num_ch; indx++)
1507 {
1508 if (channel == valid_ch[indx])
1509 {
1510 break;
1511 }
1512 }
1513
1514 if (indx >= num_ch)
1515 {
1516 hddLog(VOS_TRACE_LEVEL_ERROR,
1517 "%s: Invalid Channel [%d]", __func__, channel);
1518 return VOS_STATUS_E_FAILURE;
1519 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001520 }
1521 return VOS_STATUS_SUCCESS;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301522
Jeff Johnson295189b2012-06-20 16:38:30 -07001523}
1524
Viral Modi3a32cc52013-02-08 11:14:52 -08001525/**
1526 * FUNCTION: wlan_hdd_cfg80211_set_channel
1527 * This function is used to set the channel number
1528 */
1529static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
1530 struct ieee80211_channel *chan,
1531 enum nl80211_channel_type channel_type
1532 )
1533{
1534 v_U32_t num_ch = 0;
Jeff Johnson4416a782013-03-25 14:17:50 -07001535 int channel = 0;
Viral Modi3a32cc52013-02-08 11:14:52 -08001536 hdd_adapter_t *pAdapter = NULL;
1537 int freq = chan->center_freq; /* freq is in MHZ */
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301538 hdd_context_t *pHddCtx;
1539 int status;
Viral Modi3a32cc52013-02-08 11:14:52 -08001540
1541 ENTER();
1542
1543 if( NULL == dev )
1544 {
1545 hddLog(VOS_TRACE_LEVEL_ERROR,
1546 "%s: Called with dev = NULL.\n", __func__);
1547 return -ENODEV;
1548 }
1549 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1550
1551 hddLog(VOS_TRACE_LEVEL_INFO,
1552 "%s: device_mode = %d freq = %d \n",__func__,
1553 pAdapter->device_mode, chan->center_freq);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301554
1555 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1556 status = wlan_hdd_validate_context(pHddCtx);
1557
1558 if (0 != status)
Viral Modi3a32cc52013-02-08 11:14:52 -08001559 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301560 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1561 "%s: HDD context is not valid", __func__);
1562 return status;
Viral Modi3a32cc52013-02-08 11:14:52 -08001563 }
1564
1565 /*
1566 * Do freq to chan conversion
1567 * TODO: for 11a
1568 */
1569
1570 channel = ieee80211_frequency_to_channel(freq);
1571
1572 /* Check freq range */
1573 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
1574 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
1575 {
1576 hddLog(VOS_TRACE_LEVEL_ERROR,
1577 "%s: Channel [%d] is outside valid range from %d to %d\n",
1578 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
1579 WNI_CFG_CURRENT_CHANNEL_STAMAX);
1580 return -EINVAL;
1581 }
1582
1583 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1584
Gopichand Nakkala6ab19562013-03-07 13:59:42 +05301585 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode) &&
1586 (WLAN_HDD_P2P_GO != pAdapter->device_mode))
Viral Modi3a32cc52013-02-08 11:14:52 -08001587 {
1588 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
1589 {
1590 hddLog(VOS_TRACE_LEVEL_ERROR,
1591 "%s: Invalid Channel [%d] \n", __func__, channel);
1592 return -EINVAL;
1593 }
1594 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1595 "%s: set channel to [%d] for device mode =%d",
1596 __func__, channel,pAdapter->device_mode);
1597 }
1598 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Viral Modi3a32cc52013-02-08 11:14:52 -08001599 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Viral Modi3a32cc52013-02-08 11:14:52 -08001600 )
1601 {
1602 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
1603 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
1604 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1605
1606 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
1607 {
1608 /* Link is up then return cant set channel*/
1609 hddLog( VOS_TRACE_LEVEL_ERROR,
1610 "%s: IBSS Associated, can't set the channel\n", __func__);
1611 return -EINVAL;
1612 }
1613
1614 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
1615 pHddStaCtx->conn_info.operationChannel = channel;
1616 pRoamProfile->ChannelInfo.ChannelList =
1617 &pHddStaCtx->conn_info.operationChannel;
1618 }
1619 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Viral Modi3a32cc52013-02-08 11:14:52 -08001620 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Viral Modi3a32cc52013-02-08 11:14:52 -08001621 )
1622 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301623 if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
1624 {
1625 if(VOS_STATUS_SUCCESS !=
1626 wlan_hdd_validate_operation_channel(pAdapter,channel))
1627 {
1628 hddLog(VOS_TRACE_LEVEL_ERROR,
1629 "%s: Invalid Channel [%d] \n", __func__, channel);
1630 return -EINVAL;
1631 }
1632 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1633 }
1634 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
Viral Modi3a32cc52013-02-08 11:14:52 -08001635 {
1636 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
1637
1638 /* If auto channel selection is configured as enable/ 1 then ignore
1639 channel set by supplicant
1640 */
1641 if ( cfg_param->apAutoChannelSelection )
1642 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301643 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel =
1644 AUTO_CHANNEL_SELECT;
Viral Modi3a32cc52013-02-08 11:14:52 -08001645 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1646 "%s: set channel to auto channel (0) for device mode =%d",
1647 __func__, pAdapter->device_mode);
1648 }
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301649 else
1650 {
1651 if(VOS_STATUS_SUCCESS !=
1652 wlan_hdd_validate_operation_channel(pAdapter,channel))
1653 {
1654 hddLog(VOS_TRACE_LEVEL_ERROR,
1655 "%s: Invalid Channel [%d] \n", __func__, channel);
1656 return -EINVAL;
1657 }
1658 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1659 }
Viral Modi3a32cc52013-02-08 11:14:52 -08001660 }
1661 }
1662 else
1663 {
1664 hddLog(VOS_TRACE_LEVEL_FATAL,
1665 "%s: Invalid device mode failed to set valid channel", __func__);
1666 return -EINVAL;
1667 }
1668 EXIT();
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301669 return status;
Viral Modi3a32cc52013-02-08 11:14:52 -08001670}
1671
Jeff Johnson295189b2012-06-20 16:38:30 -07001672#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1673static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1674 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001675#else
1676static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1677 struct cfg80211_beacon_data *params,
1678 const u8 *ssid, size_t ssid_len,
1679 enum nl80211_hidden_ssid hidden_ssid)
1680#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001681{
1682 tsap_Config_t *pConfig;
1683 beacon_data_t *pBeacon = NULL;
1684 struct ieee80211_mgmt *pMgmt_frame;
1685 v_U8_t *pIe=NULL;
1686 v_U16_t capab_info;
1687 eCsrAuthType RSNAuthType;
1688 eCsrEncryptionType RSNEncryptType;
1689 eCsrEncryptionType mcRSNEncryptType;
1690 int status = VOS_STATUS_SUCCESS;
1691 tpWLAN_SAPEventCB pSapEventCallback;
1692 hdd_hostapd_state_t *pHostapdState;
1693 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1694 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301695 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001696 struct qc_mac_acl_entry *acl_entry = NULL;
1697 v_SINT_t i;
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001698 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001699
1700 ENTER();
1701
1702 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1703
1704 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1705
1706 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1707
1708 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1709
1710 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1711
1712 //channel is already set in the set_channel Call back
1713 //pConfig->channel = pCommitConfig->channel;
1714
1715 /*Protection parameter to enable or disable*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301716 pConfig->protEnabled =
Jeff Johnson295189b2012-06-20 16:38:30 -07001717 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1718
1719 pConfig->dtim_period = pBeacon->dtim_period;
1720
1721 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1722 pConfig->dtim_period);
1723
1724
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001725 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001726 {
1727 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001728 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001729 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001730 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001731 tANI_BOOLEAN restartNeeded;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001732 pConfig->ieee80211d = 1;
1733 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1734 sme_setRegInfo(hHal, pConfig->countryCode);
1735 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
Jeff Johnson295189b2012-06-20 16:38:30 -07001736 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001737 else
1738 {
1739 pConfig->ieee80211d = 0;
1740 }
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301741 /*
1742 * If auto channel is configured i.e. channel is 0,
1743 * so skip channel validation.
1744 */
1745 if( AUTO_CHANNEL_SELECT != pConfig->channel )
1746 {
1747 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1748 {
1749 hddLog(VOS_TRACE_LEVEL_ERROR,
1750 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1751 return -EINVAL;
1752 }
1753 }
1754 else
1755 {
1756 if(1 != pHddCtx->is_dynamic_channel_range_set)
1757 {
1758 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
1759 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
1760 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
1761 }
1762 pHddCtx->is_dynamic_channel_range_set = 0;
1763 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001764 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001765 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001766 {
1767 pConfig->ieee80211d = 0;
1768 }
1769 pConfig->authType = eSAP_AUTO_SWITCH;
1770
1771 capab_info = pMgmt_frame->u.beacon.capab_info;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301772
1773 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
Jeff Johnson295189b2012-06-20 16:38:30 -07001774 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1775
1776 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1777
1778 /*Set wps station to configured*/
1779 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1780
1781 if(pIe)
1782 {
1783 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1784 {
1785 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1786 return -EINVAL;
1787 }
1788 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1789 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001790 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001791 /* Check 15 bit of WPS IE as it contain information for wps state
1792 * WPS state
1793 */
1794 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1795 {
1796 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1797 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1798 {
1799 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1800 }
1801 }
1802 }
1803 else
1804 {
1805 pConfig->wps_state = SAP_WPS_DISABLED;
1806 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301807 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
Jeff Johnson295189b2012-06-20 16:38:30 -07001808
1809 pConfig->RSNWPAReqIELength = 0;
1810 pConfig->pRSNWPAReqIE = NULL;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301811 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001812 WLAN_EID_RSN);
1813 if(pIe && pIe[1])
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301814 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001815 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1816 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1817 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301818 /* The actual processing may eventually be more extensive than
1819 * this. Right now, just consume any PMKIDs that are sent in
Jeff Johnson295189b2012-06-20 16:38:30 -07001820 * by the app.
1821 * */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301822 status = hdd_softap_unpackIE(
Jeff Johnson295189b2012-06-20 16:38:30 -07001823 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1824 &RSNEncryptType,
1825 &mcRSNEncryptType,
1826 &RSNAuthType,
1827 pConfig->pRSNWPAReqIE[1]+2,
1828 pConfig->pRSNWPAReqIE );
1829
1830 if( VOS_STATUS_SUCCESS == status )
1831 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301832 /* Now copy over all the security attributes you have
1833 * parsed out
Jeff Johnson295189b2012-06-20 16:38:30 -07001834 * */
1835 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1836 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1837 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1838 = RSNEncryptType;
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05301839 hddLog( LOG1, FL("CSR AuthType = %d, "
Jeff Johnson295189b2012-06-20 16:38:30 -07001840 "EncryptionType = %d mcEncryptionType = %d\n"),
1841 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1842 }
1843 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301844
Jeff Johnson295189b2012-06-20 16:38:30 -07001845 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1846 pBeacon->tail, pBeacon->tail_len);
1847
1848 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1849 {
1850 if (pConfig->pRSNWPAReqIE)
1851 {
1852 /*Mixed mode WPA/WPA2*/
1853 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1854 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1855 }
1856 else
1857 {
1858 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1859 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1860 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301861 status = hdd_softap_unpackIE(
Jeff Johnson295189b2012-06-20 16:38:30 -07001862 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1863 &RSNEncryptType,
1864 &mcRSNEncryptType,
1865 &RSNAuthType,
1866 pConfig->pRSNWPAReqIE[1]+2,
1867 pConfig->pRSNWPAReqIE );
1868
1869 if( VOS_STATUS_SUCCESS == status )
1870 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301871 /* Now copy over all the security attributes you have
1872 * parsed out
Jeff Johnson295189b2012-06-20 16:38:30 -07001873 * */
1874 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1875 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1876 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1877 = RSNEncryptType;
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05301878 hddLog( LOG1, FL("CSR AuthType = %d, "
Jeff Johnson295189b2012-06-20 16:38:30 -07001879 "EncryptionType = %d mcEncryptionType = %d\n"),
1880 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1881 }
1882 }
1883 }
1884
Jeff Johnson4416a782013-03-25 14:17:50 -07001885 if (pConfig->RSNWPAReqIELength > sizeof wpaRsnIEdata) {
1886 hddLog( VOS_TRACE_LEVEL_ERROR, "**RSNWPAReqIELength is too large***");
1887 return -EINVAL;
1888 }
1889
Jeff Johnson295189b2012-06-20 16:38:30 -07001890 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1891
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001892#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001893 if (params->ssid != NULL)
1894 {
1895 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1896 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1897 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1898 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1899 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001900#else
1901 if (ssid != NULL)
1902 {
1903 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1904 pConfig->SSIDinfo.ssid.length = ssid_len;
1905 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1906 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1907 }
1908#endif
1909
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301910 vos_mem_copy(pConfig->self_macaddr.bytes,
Jeff Johnson295189b2012-06-20 16:38:30 -07001911 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301912
Jeff Johnson295189b2012-06-20 16:38:30 -07001913 /* default value */
1914 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1915 pConfig->num_accept_mac = 0;
1916 pConfig->num_deny_mac = 0;
1917
1918 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1919 pBeacon->tail, pBeacon->tail_len);
1920
1921 /* pIe for black list is following form:
1922 type : 1 byte
1923 length : 1 byte
1924 OUI : 4 bytes
1925 acl type : 1 byte
1926 no of mac addr in black list: 1 byte
1927 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301928 */
1929 if ((pIe != NULL) && (pIe[1] != 0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001930 {
1931 pConfig->SapMacaddr_acl = pIe[6];
1932 pConfig->num_deny_mac = pIe[7];
1933 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1934 pIe[6], pIe[7]);
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05301935 if (pConfig->num_deny_mac > MAX_ACL_MAC_ADDRESS)
1936 pConfig->num_deny_mac = MAX_ACL_MAC_ADDRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07001937 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1938 for (i = 0; i < pConfig->num_deny_mac; i++)
1939 {
1940 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1941 acl_entry++;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301942 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001943 }
1944 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1945 pBeacon->tail, pBeacon->tail_len);
1946
1947 /* pIe for white list is following form:
1948 type : 1 byte
1949 length : 1 byte
1950 OUI : 4 bytes
1951 acl type : 1 byte
1952 no of mac addr in white list: 1 byte
1953 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301954 */
1955 if ((pIe != NULL) && (pIe[1] != 0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001956 {
1957 pConfig->SapMacaddr_acl = pIe[6];
1958 pConfig->num_accept_mac = pIe[7];
1959 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
1960 pIe[6], pIe[7]);
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05301961 if (pConfig->num_accept_mac > MAX_ACL_MAC_ADDRESS)
1962 pConfig->num_accept_mac = MAX_ACL_MAC_ADDRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07001963 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1964 for (i = 0; i < pConfig->num_accept_mac; i++)
1965 {
1966 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1967 acl_entry++;
1968 }
1969 }
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05301970
Jeff Johnson295189b2012-06-20 16:38:30 -07001971 wlan_hdd_set_sapHwmode(pHostapdAdapter);
1972
Jeff Johnsone7245742012-09-05 17:12:55 -07001973#ifdef WLAN_FEATURE_11AC
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08001974 /* Overwrite the hostapd setting for HW mode only for 11ac.
1975 * This is valid only if mode is set to 11n in hostapd and either AUTO or 11ac in .ini .
1976 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode) */
1977 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
1978 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301979 (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08001980 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1981 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07001982 {
1983 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
Ravi Joshi83bfaa12013-05-28 22:12:08 -07001984
1985 /* Disable VHT support in 2.4 GHz band */
1986 if (pConfig->channel <= 14 &&
1987 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->enableVhtFor24GHzBand == FALSE)
1988 {
1989 pConfig->SapHw_mode = eSAP_DOT11_MODE_11n;
1990 }
Jeff Johnsone7245742012-09-05 17:12:55 -07001991 }
1992#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301993
Ravi Joshiaeb7d9e2013-05-02 12:28:14 -07001994 if ( AUTO_CHANNEL_SELECT != pConfig->channel )
1995 {
1996 sme_SelectCBMode(hHal,
1997 sapConvertSapPhyModeToCsrPhyMode(pConfig->SapHw_mode),
1998 pConfig->channel);
1999 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002000 // ht_capab is not what the name conveys,this is used for protection bitmap
2001 pConfig->ht_capab =
2002 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
2003
2004 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
2005 {
2006 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
2007 return -EINVAL;
2008 }
2009
2010 //Uapsd Enabled Bit
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302011 pConfig->UapsdEnable =
Jeff Johnson295189b2012-06-20 16:38:30 -07002012 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
2013 //Enable OBSS protection
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302014 pConfig->obssProtEnabled =
2015 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
Jeff Johnson295189b2012-06-20 16:38:30 -07002016
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302017 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
Jeff Johnson295189b2012-06-20 16:38:30 -07002018 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302019 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
Jeff Johnson295189b2012-06-20 16:38:30 -07002020 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
2021 (int)pConfig->channel);
2022 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302023 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
2024 pConfig->authType);
Jeff Johnson295189b2012-06-20 16:38:30 -07002025 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302026 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
Jeff Johnson295189b2012-06-20 16:38:30 -07002027 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
2028 pConfig->protEnabled, pConfig->obssProtEnabled);
2029
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302030 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07002031 {
2032 //Bss already started. just return.
2033 //TODO Probably it should update some beacon params.
2034 hddLog( LOGE, "Bss Already started...Ignore the request");
2035 EXIT();
2036 return 0;
2037 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302038
Jeff Johnson295189b2012-06-20 16:38:30 -07002039 pConfig->persona = pHostapdAdapter->device_mode;
2040
2041 pSapEventCallback = hdd_hostapd_SAPEventCB;
2042 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
2043 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
2044 {
2045 hddLog(LOGE,FL("SAP Start Bss fail\n"));
2046 return -EINVAL;
2047 }
2048
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302049 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07002050 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
2051
2052 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302053
Jeff Johnson295189b2012-06-20 16:38:30 -07002054 if (!VOS_IS_STATUS_SUCCESS(status))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302055 {
2056 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07002057 ("ERROR: HDD vos wait for single_event failed!!\n"));
2058 VOS_ASSERT(0);
2059 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302060
Jeff Johnson295189b2012-06-20 16:38:30 -07002061 //Succesfully started Bss update the state bit.
2062 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
2063
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002064#ifdef WLAN_FEATURE_P2P_DEBUG
2065 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
2066 {
2067 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
2068 {
2069 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
2070 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002071 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002072 }
2073 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
2074 {
2075 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
2076 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002077 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002078 }
2079 }
2080#endif
2081
Jeff Johnson295189b2012-06-20 16:38:30 -07002082 pHostapdState->bCommit = TRUE;
2083 EXIT();
2084
2085 return 0;
2086}
2087
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002088#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302089static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
2090 struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -07002091 struct beacon_parameters *params)
2092{
2093 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302094 hdd_context_t *pHddCtx;
2095 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002096
2097 ENTER();
2098
2099 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
2100
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302101 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2102 status = wlan_hdd_validate_context(pHddCtx);
2103
2104 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002105 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302106 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2107 "%s: HDD context is not valid", __func__);
2108 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002109 }
2110
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302111 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002112 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002113 )
2114 {
2115 beacon_data_t *old,*new;
2116
2117 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302118
Jeff Johnson295189b2012-06-20 16:38:30 -07002119 if (old)
2120 return -EALREADY;
2121
2122 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2123
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302124 if(status != VOS_STATUS_SUCCESS)
Jeff Johnson295189b2012-06-20 16:38:30 -07002125 {
2126 hddLog(VOS_TRACE_LEVEL_FATAL,
2127 "%s:Error!!! Allocating the new beacon\n",__func__);
2128 return -EINVAL;
2129 }
2130
2131 pAdapter->sessionCtx.ap.beacon = new;
2132
2133 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2134 }
2135
2136 EXIT();
2137 return status;
2138}
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302139
2140static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07002141 struct net_device *dev,
2142 struct beacon_parameters *params)
2143{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302144 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302145 hdd_context_t *pHddCtx;
2146 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002147
2148 ENTER();
2149
2150 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2151 __func__,pAdapter->device_mode);
2152
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302153 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2154 status = wlan_hdd_validate_context(pHddCtx);
2155
2156 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002157 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302158 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2159 "%s: HDD context is not valid", __func__);
2160 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002161 }
2162
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302163 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002164 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302165 )
Jeff Johnson295189b2012-06-20 16:38:30 -07002166 {
2167 beacon_data_t *old,*new;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302168
Jeff Johnson295189b2012-06-20 16:38:30 -07002169 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302170
Jeff Johnson295189b2012-06-20 16:38:30 -07002171 if (!old)
2172 return -ENOENT;
2173
2174 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2175
2176 if(status != VOS_STATUS_SUCCESS) {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302177 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -07002178 "%s: Error!!! Allocating the new beacon\n",__func__);
2179 return -EINVAL;
2180 }
2181
2182 pAdapter->sessionCtx.ap.beacon = new;
2183
2184 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2185 }
2186
2187 EXIT();
2188 return status;
2189}
2190
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002191#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
2192
2193#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002194static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
2195 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002196#else
2197static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
2198 struct net_device *dev)
2199#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002200{
2201 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07002202 hdd_context_t *pHddCtx = NULL;
2203 hdd_scaninfo_t *pScanInfo = NULL;
2204 hdd_adapter_t *staAdapter = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302205 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002206
2207 ENTER();
2208
2209 if (NULL == pAdapter)
2210 {
2211 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002212 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002213 return -ENODEV;
2214 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002215
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302216 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2217 status = wlan_hdd_validate_context(pHddCtx);
2218
2219 if (0 != status)
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002220 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302221 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2222 "%s: HDD context is not valid", __func__);
2223 return status;
Jeff Johnson4416a782013-03-25 14:17:50 -07002224 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002225
2226 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
2227 if (NULL == staAdapter)
2228 {
2229 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
2230 if (NULL == staAdapter)
2231 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302232 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002233 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002234 return -ENODEV;
2235 }
2236 }
2237
2238 pScanInfo = &pHddCtx->scan_info;
2239
Jeff Johnson295189b2012-06-20 16:38:30 -07002240 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2241 __func__,pAdapter->device_mode);
2242
Jeff Johnsone7245742012-09-05 17:12:55 -07002243 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
2244 {
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002245 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05302246 hdd_abort_mac_scan(staAdapter->pHddCtx, pAdapter->sessionId);
Jeff Johnsone7245742012-09-05 17:12:55 -07002247 status = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002248 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07002249 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
2250 if (!status)
2251 {
2252 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson902c9832012-12-10 14:28:09 -08002253 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002254 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07002255 VOS_ASSERT(pScanInfo->mScanPending);
2256 return 0;
2257 }
2258 }
2259
Jeff Johnson295189b2012-06-20 16:38:30 -07002260 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002261 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002262 )
2263 {
2264 beacon_data_t *old;
2265
2266 old = pAdapter->sessionCtx.ap.beacon;
2267
2268 if (!old)
2269 return -ENOENT;
2270
Jeff Johnson295189b2012-06-20 16:38:30 -07002271 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002272
2273 mutex_lock(&pHddCtx->sap_lock);
2274 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2275 {
Jeff Johnson4416a782013-03-25 14:17:50 -07002276 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss(pHddCtx->pvosContext) ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07002277 {
2278 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2279
2280 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2281
2282 if (!VOS_IS_STATUS_SUCCESS(status))
2283 {
2284 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2285 ("ERROR: HDD vos wait for single_event failed!!\n"));
2286 VOS_ASSERT(0);
2287 }
2288 }
2289 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2290 }
2291 mutex_unlock(&pHddCtx->sap_lock);
2292
2293 if(status != VOS_STATUS_SUCCESS)
2294 {
2295 hddLog(VOS_TRACE_LEVEL_FATAL,
2296 "%s:Error!!! Stopping the BSS\n",__func__);
2297 return -EINVAL;
2298 }
2299
Jeff Johnson4416a782013-03-25 14:17:50 -07002300 if (ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002301 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
2302 ==eHAL_STATUS_FAILURE)
2303 {
2304 hddLog(LOGE,
2305 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
2306 }
2307
Jeff Johnson4416a782013-03-25 14:17:50 -07002308 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002309 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2310 eANI_BOOLEAN_FALSE) )
2311 {
2312 hddLog(LOGE,
2313 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
2314 }
2315
2316 // Reset WNI_CFG_PROBE_RSP Flags
2317 wlan_hdd_reset_prob_rspies(pAdapter);
2318
2319 pAdapter->sessionCtx.ap.beacon = NULL;
2320 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002321#ifdef WLAN_FEATURE_P2P_DEBUG
2322 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
2323 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
2324 {
2325 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
2326 "GO got removed");
2327 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
2328 }
2329#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002330 }
2331 EXIT();
2332 return status;
2333}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002334
2335#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2336
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302337static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2338 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002339 struct cfg80211_ap_settings *params)
2340{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302341 hdd_adapter_t *pAdapter;
2342 hdd_context_t *pHddCtx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302343 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002344
2345 ENTER();
2346
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302347 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002348 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302349 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302350 "%s: Device is Null", __func__);
2351 return -ENODEV;
2352 }
2353
2354 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2355 if (NULL == pAdapter)
2356 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302357 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302358 "%s: HDD adapter is Null", __func__);
2359 return -ENODEV;
2360 }
2361
2362 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2363 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302364 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302365 "%s: HDD adapter magic is invalid", __func__);
2366 return -ENODEV;
2367 }
2368
2369 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302370 status = wlan_hdd_validate_context(pHddCtx);
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302371
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302372 if (0 != status)
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302373 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302374 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2375 "%s: HDD context is not valid", __func__);
2376 return status;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302377 }
2378
2379 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2380 __func__, pAdapter->device_mode);
2381
2382 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002383 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002384 )
2385 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302386 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002387
2388 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302389
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002390 if (old)
2391 return -EALREADY;
2392
2393 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2394
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302395 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002396 {
2397 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302398 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002399 return -EINVAL;
2400 }
2401 pAdapter->sessionCtx.ap.beacon = new;
Viral Modi3a32cc52013-02-08 11:14:52 -08002402#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Yue Maf49ba872013-08-19 12:04:25 -07002403 wlan_hdd_cfg80211_set_channel(wiphy, dev,
2404#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2405 params->channel, params->channel_type);
2406#else
2407 params->chandef.chan, cfg80211_get_chandef_type(&(params->chandef)));
2408#endif
Viral Modi3a32cc52013-02-08 11:14:52 -08002409#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002410 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2411 params->ssid_len, params->hidden_ssid);
2412 }
2413
2414 EXIT();
2415 return status;
2416}
2417
2418
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302419static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002420 struct net_device *dev,
2421 struct cfg80211_beacon_data *params)
2422{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302423 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302424 hdd_context_t *pHddCtx;
2425 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002426
2427 ENTER();
2428
2429 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2430 __func__, pAdapter->device_mode);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302431
2432 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2433 status = wlan_hdd_validate_context(pHddCtx);
2434
2435 if (0 != status)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002436 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302437 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2438 "%s: HDD context is not valid", __func__);
2439 return status;
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002440 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002441
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302442 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002443 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302444 )
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002445 {
2446 beacon_data_t *old,*new;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302447
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002448 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302449
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002450 if (!old)
2451 return -ENOENT;
2452
2453 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2454
2455 if(status != VOS_STATUS_SUCCESS) {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302456 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002457 "%s: Error!!! Allocating the new beacon\n",__func__);
2458 return -EINVAL;
2459 }
2460
2461 pAdapter->sessionCtx.ap.beacon = new;
2462
2463 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2464 }
2465
2466 EXIT();
2467 return status;
2468}
2469
2470#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2471
Jeff Johnson295189b2012-06-20 16:38:30 -07002472
2473static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2474 struct net_device *dev,
2475 struct bss_parameters *params)
2476{
2477 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2478
2479 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302480
Jeff Johnson295189b2012-06-20 16:38:30 -07002481 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2482 __func__,pAdapter->device_mode);
2483
2484 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002485 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302486 )
Jeff Johnson295189b2012-06-20 16:38:30 -07002487 {
2488 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2489 * want to update this parameter */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302490 if (-1 != params->ap_isolate)
Jeff Johnson295189b2012-06-20 16:38:30 -07002491 {
2492 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302493 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002494 }
2495
2496 EXIT();
2497 return 0;
2498}
2499
2500/*
2501 * FUNCTION: wlan_hdd_cfg80211_change_iface
2502 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2503 */
2504int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2505 struct net_device *ndev,
2506 enum nl80211_iftype type,
2507 u32 *flags,
2508 struct vif_params *params
2509 )
2510{
2511 struct wireless_dev *wdev;
2512 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2513 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002514 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002515 tCsrRoamProfile *pRoamProfile = NULL;
2516 eCsrRoamBssType LastBSSType;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302517 hdd_config_t *pConfig = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002518 eMib_dot11DesiredBssType connectedBssType;
2519 VOS_STATUS status;
2520
2521 ENTER();
2522
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302523 status = wlan_hdd_validate_context(pHddCtx);
2524
2525 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07002526 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302527 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2528 "%s: HDD context is not valid", __func__);
2529 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002530 }
2531
2532 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2533 __func__, pAdapter->device_mode);
2534
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302535 pConfig = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07002536 wdev = ndev->ieee80211_ptr;
2537
2538#ifdef WLAN_BTAMP_FEATURE
2539 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2540 (NL80211_IFTYPE_ADHOC == type)||
2541 (NL80211_IFTYPE_AP == type)||
2542 (NL80211_IFTYPE_P2P_GO == type))
2543 {
2544 pHddCtx->isAmpAllowed = VOS_FALSE;
2545 // stop AMP traffic
2546 status = WLANBAP_StopAmp();
2547 if(VOS_STATUS_SUCCESS != status )
2548 {
2549 pHddCtx->isAmpAllowed = VOS_TRUE;
2550 hddLog(VOS_TRACE_LEVEL_FATAL,
2551 "%s: Failed to stop AMP", __func__);
2552 return -EINVAL;
2553 }
2554 }
2555#endif //WLAN_BTAMP_FEATURE
2556 /* Reset the current device mode bit mask*/
2557 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2558
2559 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07002560 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002561 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002562 )
2563 {
2564 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2565 pRoamProfile = &pWextState->roamProfile;
2566 LastBSSType = pRoamProfile->BSSType;
2567
2568 switch (type)
2569 {
2570 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002571 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002572 hddLog(VOS_TRACE_LEVEL_INFO,
2573 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2574 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002575#ifdef WLAN_FEATURE_11AC
2576 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2577 {
2578 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2579 }
2580#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302581 pRoamProfile->phyMode =
Jeff Johnsone7245742012-09-05 17:12:55 -07002582 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002583 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002584 //Check for sub-string p2p to confirm its a p2p interface
2585 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302586 {
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002587 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2588 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2589 }
2590 else
2591 {
2592 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002593 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002594 }
Madan Mohan Koyyalamudi81746922013-07-17 14:38:51 +05302595#ifdef FEATURE_WLAN_TDLS
2596 /* The open adapter for the p2p shall skip initializations in
2597 * tdls_init if the device mode is WLAN_HDD_P2P_DEVICE, for
2598 * TDLS is supported only on WLAN_HDD_P2P_CLIENT. Hence invoke
2599 * tdls_init when the change_iface sets the device mode to
2600 * WLAN_HDD_P2P_CLIENT.
2601 */
2602
2603 if ( pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2604 {
2605 if (0 != wlan_hdd_tdls_init (pAdapter))
2606 {
2607 return -EINVAL;
2608 }
2609 }
2610#endif
2611
Jeff Johnson295189b2012-06-20 16:38:30 -07002612 break;
2613 case NL80211_IFTYPE_ADHOC:
2614 hddLog(VOS_TRACE_LEVEL_INFO,
2615 "%s: setting interface Type to ADHOC", __func__);
2616 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2617 pRoamProfile->phyMode =
2618 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Shailender Karmuchia734f332013-04-19 14:02:48 -07002619 pAdapter->device_mode = WLAN_HDD_IBSS;
Jeff Johnson295189b2012-06-20 16:38:30 -07002620 wdev->iftype = type;
2621 break;
2622
2623 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002624 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002625 {
2626 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2627 "%s: setting interface Type to %s", __func__,
2628 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2629
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002630 //Cancel any remain on channel for GO mode
2631 if (NL80211_IFTYPE_P2P_GO == type)
2632 {
2633 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2634 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002635 if (NL80211_IFTYPE_AP == type)
2636 {
2637 /* As Loading WLAN Driver one interface being created for p2p device
2638 * address. This will take one HW STA and the max number of clients
2639 * that can connect to softAP will be reduced by one. so while changing
2640 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2641 * interface as it is not required in SoftAP mode.
2642 */
2643
2644 // Get P2P Adapter
2645 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2646
2647 if (pP2pAdapter)
2648 {
2649 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2650 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2651 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2652 }
2653 }
2654
Jeff Johnson295189b2012-06-20 16:38:30 -07002655 //De-init the adapter.
2656 hdd_stop_adapter( pHddCtx, pAdapter );
2657 hdd_deinit_adapter( pHddCtx, pAdapter );
2658 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
Jeff Johnson295189b2012-06-20 16:38:30 -07002659 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2660 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002661
2662 //Disable BMPS and IMPS if enabled
2663 //before starting Go
2664 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2665 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302666 if(VOS_STATUS_E_FAILURE ==
Jeff Johnson32d95a32012-09-10 13:15:23 -07002667 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2668 {
2669 //Fail to Exit BMPS
2670 VOS_ASSERT(0);
2671 }
2672 }
2673
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002674 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2675 (pConfig->apRandomBssidEnabled))
2676 {
2677 /* To meet Android requirements create a randomized
2678 MAC address of the form 02:1A:11:Fx:xx:xx */
2679 get_random_bytes(&ndev->dev_addr[3], 3);
2680 ndev->dev_addr[0] = 0x02;
2681 ndev->dev_addr[1] = 0x1A;
2682 ndev->dev_addr[2] = 0x11;
2683 ndev->dev_addr[3] |= 0xF0;
2684 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2685 VOS_MAC_ADDR_SIZE);
2686 pr_info("wlan: Generated HotSpot BSSID "
2687 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2688 ndev->dev_addr[0],
2689 ndev->dev_addr[1],
2690 ndev->dev_addr[2],
2691 ndev->dev_addr[3],
2692 ndev->dev_addr[4],
2693 ndev->dev_addr[5]);
2694 }
2695
Jeff Johnson295189b2012-06-20 16:38:30 -07002696 hdd_set_ap_ops( pAdapter->dev );
2697
2698 status = hdd_init_ap_mode(pAdapter);
2699 if(status != VOS_STATUS_SUCCESS)
2700 {
2701 hddLog(VOS_TRACE_LEVEL_FATAL,
2702 "%s: Error initializing the ap mode", __func__);
2703 return -EINVAL;
2704 }
2705 hdd_set_conparam(1);
2706
Jeff Johnson295189b2012-06-20 16:38:30 -07002707 /*interface type changed update in wiphy structure*/
2708 if(wdev)
2709 {
2710 wdev->iftype = type;
2711 pHddCtx->change_iface = type;
2712 }
2713 else
2714 {
2715 hddLog(VOS_TRACE_LEVEL_ERROR,
2716 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2717 return -EINVAL;
2718 }
2719 goto done;
2720 }
2721
2722 default:
2723 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2724 __func__);
2725 return -EOPNOTSUPP;
2726 }
2727 }
2728 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002729 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002730 )
2731 {
2732 switch(type)
2733 {
2734 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002735 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002736 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002737 hdd_stop_adapter( pHddCtx, pAdapter );
2738 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002739 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002740 //Check for sub-string p2p to confirm its a p2p interface
2741 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002742 {
2743 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2744 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2745 }
2746 else
2747 {
2748 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002749 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002750 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002751 hdd_set_conparam(0);
2752 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002753 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2754 hdd_set_station_ops( pAdapter->dev );
2755 status = hdd_init_station_mode( pAdapter );
2756 if( VOS_STATUS_SUCCESS != status )
2757 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002758 /* In case of JB, for P2P-GO, only change interface will be called,
2759 * This is the right place to enable back bmps_imps()
2760 */
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05302761 if (pHddCtx->hdd_wlan_suspended)
2762 {
2763 hdd_set_pwrparams(pHddCtx);
2764 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002765 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002766 goto done;
2767 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002768 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002769 wdev->iftype = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002770 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2771 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07002772 goto done;
2773 default:
2774 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2775 __func__);
2776 return -EOPNOTSUPP;
2777
2778 }
2779
2780 }
2781 else
2782 {
2783 return -EOPNOTSUPP;
2784 }
2785
2786
2787 if(pRoamProfile)
2788 {
2789 if ( LastBSSType != pRoamProfile->BSSType )
2790 {
2791 /*interface type changed update in wiphy structure*/
2792 wdev->iftype = type;
2793
2794 /*the BSS mode changed, We need to issue disconnect
2795 if connected or in IBSS disconnect state*/
2796 if ( hdd_connGetConnectedBssType(
2797 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2798 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2799 {
2800 /*need to issue a disconnect to CSR.*/
2801 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2802 if( eHAL_STATUS_SUCCESS ==
2803 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2804 pAdapter->sessionId,
2805 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2806 {
2807 wait_for_completion_interruptible_timeout(
2808 &pAdapter->disconnect_comp_var,
2809 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2810 }
2811 }
2812 }
2813 }
2814
2815done:
2816 /*set bitmask based on updated value*/
2817 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
Leo Chang6fe1f922013-06-07 19:21:24 -07002818
2819 /* Only STA mode support TM now
2820 * all other mode, TM feature should be disabled */
2821 if ( (pHddCtx->cfg_ini->thermalMitigationEnable) &&
2822 (~VOS_STA & pHddCtx->concurrency_mode) )
2823 {
2824 hddDevTmLevelChangedHandler(pHddCtx->parent_dev, 0);
2825 }
2826
Jeff Johnson295189b2012-06-20 16:38:30 -07002827#ifdef WLAN_BTAMP_FEATURE
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302828 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07002829 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2830 {
2831 //we are ok to do AMP
2832 pHddCtx->isAmpAllowed = VOS_TRUE;
2833 }
2834#endif //WLAN_BTAMP_FEATURE
2835 EXIT();
2836 return 0;
2837}
2838
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002839#ifdef FEATURE_WLAN_TDLS
2840static int wlan_hdd_tdls_add_station(struct wiphy *wiphy,
2841 struct net_device *dev, u8 *mac, bool update, tCsrStaParams *StaParams)
2842{
2843 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2844 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2845 VOS_STATUS status;
Hoonki Lee5305c3a2013-04-29 23:28:59 -07002846 hddTdlsPeer_t *pTdlsPeer;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002847
2848 ENTER();
2849
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05302850 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002851 {
2852 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2853 "Invalid arguments");
2854 return -EINVAL;
2855 }
Hoonki Lee27511902013-03-14 18:19:06 -07002856
2857 if ((eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) ||
2858 (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode))
2859 {
2860 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2861 "%s: TDLS mode is disabled OR not enabled in FW."
2862 MAC_ADDRESS_STR " Request declined.",
2863 __func__, MAC_ADDR_ARRAY(mac));
2864 return -ENOTSUPP;
2865 }
2866
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002867 if (pHddCtx->isLogpInProgress)
2868 {
2869 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2870 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07002871 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002872 return -EBUSY;
2873 }
2874
Hoonki Lee5305c3a2013-04-29 23:28:59 -07002875 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac);
2876
2877 if ( NULL == pTdlsPeer ) {
2878 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2879 "%s: " MAC_ADDRESS_STR " (update %d) not exist. return invalid",
2880 __func__, MAC_ADDR_ARRAY(mac), update);
2881 return -EINVAL;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002882 }
Hoonki Lee5305c3a2013-04-29 23:28:59 -07002883
2884 /* in add station, we accept existing valid staId if there is */
2885 if ((0 == update) &&
2886 ((pTdlsPeer->link_status >= eTDLS_LINK_CONNECTING) ||
2887 (TDLS_STA_INDEX_VALID(pTdlsPeer->staId))))
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002888 {
Hoonki Lee5305c3a2013-04-29 23:28:59 -07002889 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002890 "%s: " MAC_ADDRESS_STR
Hoonki Lee5305c3a2013-04-29 23:28:59 -07002891 " link_status %d. staId %d. add station ignored.",
2892 __func__, MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status, pTdlsPeer->staId);
2893 return 0;
2894 }
2895 /* in change station, we accept only when staId is valid */
2896 if ((1 == update) &&
2897 ((pTdlsPeer->link_status > eTDLS_LINK_CONNECTING) ||
2898 (!TDLS_STA_INDEX_VALID(pTdlsPeer->staId))))
2899 {
2900 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2901 "%s: " MAC_ADDRESS_STR
2902 " link status %d. staId %d. change station %s.",
2903 __func__, MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status, pTdlsPeer->staId,
2904 (TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) ? "ignored" : "declined");
2905 return (TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) ? 0 : -EPERM;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002906 }
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002907
2908 /* when others are on-going, we want to change link_status to idle */
Hoonki Leefb8df672013-04-10 18:20:34 -07002909 if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, mac, TRUE, TRUE))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002910 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002911 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2912 "%s: " MAC_ADDRESS_STR
2913 " TDLS setup is ongoing. Request declined.",
2914 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002915 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002916 }
2917
2918 /* first to check if we reached to maximum supported TDLS peer.
2919 TODO: for now, return -EPERM looks working fine,
2920 but need to check if any other errno fit into this category.*/
2921 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
2922 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002923 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2924 "%s: " MAC_ADDRESS_STR
2925 " TDLS Max peer already connected. Request declined.",
2926 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002927 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002928 }
2929 else
2930 {
2931 hddTdlsPeer_t *pTdlsPeer;
2932 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002933 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002934 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002935 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2936 "%s: " MAC_ADDRESS_STR " already connected. Request declined.",
2937 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002938 return -EPERM;
2939 }
2940 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002941 if (0 == update)
2942 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_CONNECTING);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002943
Jeff Johnsond75fe012013-04-06 10:53:06 -07002944 /* debug code */
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05302945 if (NULL != StaParams)
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002946 {
2947 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2948 "%s: TDLS Peer Parameters.", __func__);
Hoonki Lee66b75f32013-04-16 18:30:07 -07002949 if(StaParams->htcap_present)
2950 {
2951 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2952 "ht_capa->cap_info: %0x", StaParams->HTCap.capInfo);
2953 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2954 "ht_capa->extended_capabilities: %0x",
2955 StaParams->HTCap.extendedHtCapInfo);
2956 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002957 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2958 "params->capability: %0x",StaParams->capability);
2959 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2960 "params->ext_capab_len: %0x",StaParams->extn_capability);
Hoonki Lee66b75f32013-04-16 18:30:07 -07002961 if(StaParams->vhtcap_present)
2962 {
2963 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2964 "rxMcsMap %x rxHighest %x txMcsMap %x txHighest %x",
2965 StaParams->VHTCap.suppMcs.rxMcsMap, StaParams->VHTCap.suppMcs.rxHighest,
2966 StaParams->VHTCap.suppMcs.txMcsMap, StaParams->VHTCap.suppMcs.txHighest);
2967 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002968 {
2969 int i = 0;
Hoonki Lee5305c3a2013-04-29 23:28:59 -07002970 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "Supported rates:");
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002971 for (i = 0; i < sizeof(StaParams->supported_rates); i++)
2972 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2973 "[%d]: %x ", i, StaParams->supported_rates[i]);
2974 }
Jeff Johnsond75fe012013-04-06 10:53:06 -07002975 } /* end debug code */
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05302976 else if ((1 == update) && (NULL == StaParams))
2977 {
2978 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2979 "%s : update is true, but staParams is NULL. Error!", __func__);
2980 return -EPERM;
2981 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002982
2983 INIT_COMPLETION(pAdapter->tdls_add_station_comp);
2984
2985 if (!update)
2986 {
2987 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
2988 pAdapter->sessionId, mac);
2989 }
2990 else
2991 {
2992 status = sme_ChangeTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
2993 pAdapter->sessionId, mac, StaParams);
2994 }
2995
2996 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_add_station_comp,
2997 msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
2998
2999 if (!status)
3000 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003001 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003002 "%s: timeout waiting for tdls add station indication",
3003 __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07003004 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003005 }
3006 if ( eHAL_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus)
3007 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003008 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003009 "%s: Add Station is unsucessful", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07003010 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003011 }
3012
3013 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07003014
3015error:
3016 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
3017 return -EPERM;
3018
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003019}
3020#endif
3021
Jeff Johnson295189b2012-06-20 16:38:30 -07003022static int wlan_hdd_change_station(struct wiphy *wiphy,
3023 struct net_device *dev,
3024 u8 *mac,
3025 struct station_parameters *params)
3026{
3027 VOS_STATUS status = VOS_STATUS_SUCCESS;
3028 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Gopichand Nakkala29149562013-05-10 21:43:41 +05303029 hdd_context_t *pHddCtx;
3030 hdd_station_ctx_t *pHddStaCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003031 v_MACADDR_t STAMacAddress;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003032#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003033 tCsrStaParams StaParams = {0};
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003034 tANI_U8 isBufSta = 0;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003035#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003036 ENTER();
3037
Gopichand Nakkala29149562013-05-10 21:43:41 +05303038 if ((NULL == pAdapter))
3039 {
3040 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3041 "invalid adapter ");
3042 return -EINVAL;
3043 }
3044
3045 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3046 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3047
3048 if ((NULL == pHddCtx) || (NULL == pHddStaCtx))
3049 {
3050 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3051 "invalid HDD state or HDD station context");
3052 return -EINVAL;
3053 }
3054
3055 if (pHddCtx->isLogpInProgress)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003056 {
3057 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3058 "%s:LOGP in Progress. Ignore!!!", __func__);
3059 return -EAGAIN;
3060 }
3061
Jeff Johnson295189b2012-06-20 16:38:30 -07003062 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
3063
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003064 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3065 || (pAdapter->device_mode == WLAN_HDD_P2P_GO))
Jeff Johnson295189b2012-06-20 16:38:30 -07003066 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003067 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
Jeff Johnson295189b2012-06-20 16:38:30 -07003068 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303069 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
Jeff Johnson295189b2012-06-20 16:38:30 -07003070 WLANTL_STA_AUTHENTICATED);
3071
Gopichand Nakkala29149562013-05-10 21:43:41 +05303072 if (status != VOS_STATUS_SUCCESS)
3073 {
3074 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3075 "%s: Not able to change TL state to AUTHENTICATED", __func__);
3076 return -EINVAL;
3077 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003078 }
3079 }
Hoonki Leea6d49be2013-04-05 09:43:25 -07003080 else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3081 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) {
Gopichand Nakkala29149562013-05-10 21:43:41 +05303082#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003083 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
3084 StaParams.capability = params->capability;
3085 StaParams.uapsd_queues = params->uapsd_queues;
3086 StaParams.max_sp = params->max_sp;
3087
3088 if (0 != params->ext_capab_len)
3089 vos_mem_copy(StaParams.extn_capability, params->ext_capab,
3090 sizeof(StaParams.extn_capability));
3091
3092 if (NULL != params->ht_capa)
Hoonki Lee66b75f32013-04-16 18:30:07 -07003093 {
3094 StaParams.htcap_present = 1;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003095 vos_mem_copy(&StaParams.HTCap, params->ht_capa, sizeof(tSirHTCap));
Hoonki Lee66b75f32013-04-16 18:30:07 -07003096 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003097
3098 StaParams.supported_rates_len = params->supported_rates_len;
3099
3100 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
3101 * The supported_rates array , for all the structures propogating till Add Sta
3102 * to the firmware has to be modified , if the supplicant (ieee80211) is
3103 * modified to send more rates.
3104 */
3105
3106 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
3107 */
3108 if (StaParams.supported_rates_len > SIR_MAC_MAX_SUPP_RATES)
3109 StaParams.supported_rates_len = SIR_MAC_MAX_SUPP_RATES;
3110
3111 if (0 != StaParams.supported_rates_len) {
3112 int i = 0;
3113 vos_mem_copy(StaParams.supported_rates, params->supported_rates,
3114 StaParams.supported_rates_len);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003115 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003116 "Supported Rates with Length %d", StaParams.supported_rates_len);
3117 for (i=0; i < StaParams.supported_rates_len; i++)
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003118 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003119 "[%d]: %0x", i, StaParams.supported_rates[i]);
3120 }
3121
3122 if (NULL != params->vht_capa)
Hoonki Lee66b75f32013-04-16 18:30:07 -07003123 {
3124 StaParams.vhtcap_present = 1;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003125 vos_mem_copy(&StaParams.VHTCap, params->vht_capa, sizeof(tSirVHTCap));
Hoonki Lee66b75f32013-04-16 18:30:07 -07003126 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003127
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003128 if (0 != params->ext_capab_len ) {
3129 /*Define A Macro : TODO Sunil*/
3130 if ((1<<4) & StaParams.extn_capability[3]) {
3131 isBufSta = 1;
3132 }
3133 }
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303134 status = wlan_hdd_tdls_set_peer_caps( pAdapter, mac, params->uapsd_queues,
3135 params->max_sp, isBufSta);
3136 if (VOS_STATUS_SUCCESS != status) {
3137 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3138 "%s: wlan_hdd_tdls_set_peer_caps failed!", __func__);
3139 return -EINVAL;
3140 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003141 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 1, &StaParams);
3142
3143 if (VOS_STATUS_SUCCESS != status) {
3144 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3145 "%s: sme_ChangeTdlsPeerSta failed!", __func__);
3146 return -EINVAL;
3147 }
3148 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003149#endif
Gopichand Nakkala6239acd2013-06-14 14:48:00 +05303150 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003151 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003152 return status;
3153}
3154
3155/*
Jeff Johnson295189b2012-06-20 16:38:30 -07003156 * FUNCTION: wlan_hdd_cfg80211_add_key
3157 * This function is used to initialize the key information
3158 */
3159#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003160static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003161 struct net_device *ndev,
3162 u8 key_index, bool pairwise,
3163 const u8 *mac_addr,
3164 struct key_params *params
3165 )
3166#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003167static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003168 struct net_device *ndev,
3169 u8 key_index, const u8 *mac_addr,
3170 struct key_params *params
3171 )
3172#endif
3173{
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003174 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003175 tCsrRoamSetKey setKey;
3176 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303177 int status;
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003178 v_U32_t roamId= 0xFF;
3179 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003180 hdd_hostapd_state_t *pHostapdState;
3181 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003182 eHalStatus halStatus;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303183 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003184
3185 ENTER();
3186
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303187 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3188 status = wlan_hdd_validate_context(pHddCtx);
3189
3190 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003191 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303192 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3193 "%s: HDD context is not valid", __func__);
3194 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003195 }
3196
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003197 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
3198 __func__, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003199
3200 if (CSR_MAX_NUM_KEY <= key_index)
3201 {
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003202 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003203 key_index);
3204
3205 return -EINVAL;
3206 }
3207
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003208 if (CSR_MAX_KEY_LEN < params->key_len)
3209 {
3210 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key length %d", __func__,
3211 params->key_len);
3212
3213 return -EINVAL;
3214 }
3215
3216 hddLog(VOS_TRACE_LEVEL_INFO,
3217 "%s: called with key index = %d & key length %d",
3218 __func__, key_index, params->key_len);
Jeff Johnson295189b2012-06-20 16:38:30 -07003219
3220 /*extract key idx, key len and key*/
3221 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3222 setKey.keyId = key_index;
3223 setKey.keyLength = params->key_len;
3224 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
3225
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003226 switch (params->cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07003227 {
3228 case WLAN_CIPHER_SUITE_WEP40:
3229 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
3230 break;
3231
3232 case WLAN_CIPHER_SUITE_WEP104:
3233 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
3234 break;
3235
3236 case WLAN_CIPHER_SUITE_TKIP:
3237 {
3238 u8 *pKey = &setKey.Key[0];
3239 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
3240
3241 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
3242
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003243 /*Supplicant sends the 32bytes key in this order
Jeff Johnson295189b2012-06-20 16:38:30 -07003244
3245 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003246 | Tk1 |TX-MIC | RX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003247 |--------------|----------|----------|
3248 <---16bytes---><--8bytes--><--8bytes-->
3249
3250 */
3251 /*Sme expects the 32 bytes key to be in the below order
3252
3253 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003254 | Tk1 |RX-MIC | TX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003255 |--------------|----------|----------|
3256 <---16bytes---><--8bytes--><--8bytes-->
3257 */
3258 /* Copy the Temporal Key 1 (TK1) */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003259 vos_mem_copy(pKey, params->key, 16);
Jeff Johnson295189b2012-06-20 16:38:30 -07003260
3261 /*Copy the rx mic first*/
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003262 vos_mem_copy(&pKey[16], &params->key[24], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003263
3264 /*Copy the tx mic */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003265 vos_mem_copy(&pKey[24], &params->key[16], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003266
3267
3268 break;
3269 }
3270
3271 case WLAN_CIPHER_SUITE_CCMP:
3272 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
3273 break;
3274
3275#ifdef FEATURE_WLAN_WAPI
3276 case WLAN_CIPHER_SUITE_SMS4:
3277 {
3278 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3279 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
3280 params->key, params->key_len);
3281 return 0;
3282 }
3283#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003284
Jeff Johnson295189b2012-06-20 16:38:30 -07003285#ifdef FEATURE_WLAN_CCX
3286 case WLAN_CIPHER_SUITE_KRK:
3287 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
3288 break;
3289#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003290
3291#ifdef WLAN_FEATURE_11W
3292 case WLAN_CIPHER_SUITE_AES_CMAC:
3293 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
Chet Lanctot3b5158a2013-03-31 16:45:21 -07003294 break;
Chet Lanctot186b5732013-03-18 10:26:30 -07003295#endif
3296
Jeff Johnson295189b2012-06-20 16:38:30 -07003297 default:
3298 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
3299 __func__, params->cipher);
3300 return -EOPNOTSUPP;
3301 }
3302
3303 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
3304 __func__, setKey.encType);
3305
Shailender Karmuchi642e9812013-05-30 14:34:49 -07003306 if (
Jeff Johnson295189b2012-06-20 16:38:30 -07003307#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3308 (!pairwise)
3309#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003310 (!mac_addr || is_broadcast_ether_addr(mac_addr))
Jeff Johnson295189b2012-06-20 16:38:30 -07003311#endif
Shailender Karmuchi642e9812013-05-30 14:34:49 -07003312 )
3313 {
3314 /* set group key*/
3315 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3316 "%s- %d: setting Broadcast key",
3317 __func__, __LINE__);
3318 setKey.keyDirection = eSIR_RX_ONLY;
3319 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3320 }
3321 else
3322 {
3323 /* set pairwise key*/
3324 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3325 "%s- %d: setting pairwise key",
3326 __func__, __LINE__);
3327 setKey.keyDirection = eSIR_TX_RX;
3328 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3329 }
3330 if ((WLAN_HDD_IBSS == pAdapter->device_mode) && !pairwise)
3331 {
3332 setKey.keyDirection = eSIR_TX_RX;
3333 /*Set the group key*/
3334 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3335 pAdapter->sessionId, &setKey, &roamId );
Jeff Johnson295189b2012-06-20 16:38:30 -07003336
Shailender Karmuchi642e9812013-05-30 14:34:49 -07003337 if ( 0 != status )
3338 {
3339 hddLog(VOS_TRACE_LEVEL_ERROR,
3340 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3341 return -EINVAL;
3342 }
3343 /*Save the keys here and call sme_RoamSetKey for setting
3344 the PTK after peer joins the IBSS network*/
3345 vos_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
3346 &setKey, sizeof(tCsrRoamSetKey));
3347 return status;
3348 }
Gopichand Nakkala29149562013-05-10 21:43:41 +05303349 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) ||
3350 (pAdapter->device_mode == WLAN_HDD_P2P_GO))
3351 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003352 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003353 if( pHostapdState->bssState == BSS_START )
3354 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003355 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3356
3357 if ( status != eHAL_STATUS_SUCCESS )
3358 {
3359 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3360 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3361 __LINE__, status );
3362 }
3363 }
3364
3365 /* Saving WEP keys */
3366 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
3367 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
3368 {
3369 //Save the wep key in ap context. Issue setkey after the BSS is started.
3370 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3371 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
3372 }
3373 else
3374 {
3375 //Save the key in ap context. Issue setkey after the BSS is started.
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003376 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003377 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
3378 }
3379 }
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003380 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
3381 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) )
Jeff Johnson295189b2012-06-20 16:38:30 -07003382 {
3383 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3384 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3385
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303386#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3387 if (!pairwise)
3388#else
3389 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
3390#endif
3391 {
3392 /* set group key*/
3393 if (pHddStaCtx->roam_info.deferKeyComplete)
3394 {
3395 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3396 "%s- %d: Perform Set key Complete",
3397 __func__, __LINE__);
3398 hdd_PerformRoamSetKeyComplete(pAdapter);
3399 }
3400 }
3401
Jeff Johnson295189b2012-06-20 16:38:30 -07003402 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
3403
Venkata Prathyusha Kuntupalliee2ce712013-01-17 14:09:24 -08003404 pWextState->roamProfile.Keys.defaultIndex = key_index;
3405
3406
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003407 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07003408 params->key, params->key_len);
3409
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303410
Jeff Johnson295189b2012-06-20 16:38:30 -07003411 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3412
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303413 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07003414 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303415 __func__, setKey.peerMac[0], setKey.peerMac[1],
3416 setKey.peerMac[2], setKey.peerMac[3],
3417 setKey.peerMac[4], setKey.peerMac[5],
Jeff Johnson295189b2012-06-20 16:38:30 -07003418 setKey.keyDirection);
3419
3420 vos_status = wlan_hdd_check_ula_done(pAdapter);
3421
3422 if ( vos_status != VOS_STATUS_SUCCESS )
3423 {
3424 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3425 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
3426 __LINE__, vos_status );
3427
3428 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3429
3430 return -EINVAL;
3431
3432 }
3433
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003434#ifdef WLAN_FEATURE_VOWIFI_11R
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303435 /* The supplicant may attempt to set the PTK once pre-authentication
3436 is done. Save the key in the UMAC and include it in the ADD BSS
3437 request */
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003438 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303439 if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS )
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003440 {
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303441 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3442 "%s: Update PreAuth Key success", __func__);
3443 return 0;
3444 }
3445 else if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_FAILED )
3446 {
3447 hddLog(VOS_TRACE_LEVEL_ERROR,
3448 "%s: Update PreAuth Key failed", __func__);
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303449 return -EINVAL;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003450 }
3451#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07003452
3453 /* issue set key request to SME*/
3454 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3455 pAdapter->sessionId, &setKey, &roamId );
3456
3457 if ( 0 != status )
3458 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303459 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003460 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3461 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3462 return -EINVAL;
3463 }
3464
3465
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303466 /* in case of IBSS as there was no information available about WEP keys during
3467 * IBSS join, group key intialized with NULL key, so re-initialize group key
Jeff Johnson295189b2012-06-20 16:38:30 -07003468 * with correct value*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303469 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
3470 !( ( IW_AUTH_KEY_MGMT_802_1X
3471 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
Jeff Johnson295189b2012-06-20 16:38:30 -07003472 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3473 )
3474 &&
3475 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3476 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3477 )
3478 )
3479 {
3480 setKey.keyDirection = eSIR_RX_ONLY;
3481 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3482
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303483 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07003484 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303485 __func__, setKey.peerMac[0], setKey.peerMac[1],
3486 setKey.peerMac[2], setKey.peerMac[3],
3487 setKey.peerMac[4], setKey.peerMac[5],
Jeff Johnson295189b2012-06-20 16:38:30 -07003488 setKey.keyDirection);
3489
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303490 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07003491 pAdapter->sessionId, &setKey, &roamId );
3492
3493 if ( 0 != status )
3494 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303495 hddLog(VOS_TRACE_LEVEL_ERROR,
3496 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07003497 __func__, status);
3498 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3499 return -EINVAL;
3500 }
3501 }
3502 }
3503
3504 return 0;
3505}
3506
3507/*
3508 * FUNCTION: wlan_hdd_cfg80211_get_key
3509 * This function is used to get the key information
3510 */
3511#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303512static int wlan_hdd_cfg80211_get_key(
3513 struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003514 struct net_device *ndev,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303515 u8 key_index, bool pairwise,
Jeff Johnson295189b2012-06-20 16:38:30 -07003516 const u8 *mac_addr, void *cookie,
3517 void (*callback)(void *cookie, struct key_params*)
3518 )
3519#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303520static int wlan_hdd_cfg80211_get_key(
3521 struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003522 struct net_device *ndev,
3523 u8 key_index, const u8 *mac_addr, void *cookie,
3524 void (*callback)(void *cookie, struct key_params*)
3525 )
3526#endif
3527{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303528 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003529 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3530 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
3531 struct key_params params;
3532
3533 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303534
Jeff Johnson295189b2012-06-20 16:38:30 -07003535 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3536 __func__,pAdapter->device_mode);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303537
Jeff Johnson295189b2012-06-20 16:38:30 -07003538 memset(&params, 0, sizeof(params));
3539
3540 if (CSR_MAX_NUM_KEY <= key_index)
3541 {
3542 return -EINVAL;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303543 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003544
3545 switch(pRoamProfile->EncryptionType.encryptionType[0])
3546 {
3547 case eCSR_ENCRYPT_TYPE_NONE:
3548 params.cipher = IW_AUTH_CIPHER_NONE;
3549 break;
3550
3551 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3552 case eCSR_ENCRYPT_TYPE_WEP40:
3553 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3554 break;
3555
3556 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3557 case eCSR_ENCRYPT_TYPE_WEP104:
3558 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3559 break;
3560
3561 case eCSR_ENCRYPT_TYPE_TKIP:
3562 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3563 break;
3564
3565 case eCSR_ENCRYPT_TYPE_AES:
3566 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3567 break;
3568
3569 default:
3570 params.cipher = IW_AUTH_CIPHER_NONE;
3571 break;
3572 }
3573
3574 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3575 params.seq_len = 0;
3576 params.seq = NULL;
3577 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3578 callback(cookie, &params);
3579 return 0;
3580}
3581
3582/*
3583 * FUNCTION: wlan_hdd_cfg80211_del_key
3584 * This function is used to delete the key information
3585 */
3586#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303587static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003588 struct net_device *ndev,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303589 u8 key_index,
3590 bool pairwise,
Jeff Johnson295189b2012-06-20 16:38:30 -07003591 const u8 *mac_addr
3592 )
3593#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303594static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003595 struct net_device *ndev,
3596 u8 key_index,
3597 const u8 *mac_addr
3598 )
3599#endif
3600{
3601 int status = 0;
3602
3603 //This code needs to be revisited. There is sme_removeKey API, we should
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303604 //plan to use that. After the change to use correct index in setkey,
Jeff Johnson295189b2012-06-20 16:38:30 -07003605 //it is observed that this is invalidating peer
3606 //key index whenever re-key is done. This is affecting data link.
3607 //It should be ok to ignore del_key.
3608#if 0
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303609 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3610 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003611 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3612 tCsrRoamSetKey setKey;
3613 v_U32_t roamId= 0xFF;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303614
Jeff Johnson295189b2012-06-20 16:38:30 -07003615 ENTER();
3616
3617 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3618 __func__,pAdapter->device_mode);
3619
3620 if (CSR_MAX_NUM_KEY <= key_index)
3621 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303622 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003623 key_index);
3624
3625 return -EINVAL;
3626 }
3627
3628 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3629 setKey.keyId = key_index;
3630
3631 if (mac_addr)
3632 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3633 else
3634 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3635
3636 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3637
3638 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003639 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303640 )
3641 {
3642
3643 hdd_hostapd_state_t *pHostapdState =
Jeff Johnson295189b2012-06-20 16:38:30 -07003644 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3645 if( pHostapdState->bssState == BSS_START)
3646 {
3647 status = WLANSAP_SetKeySta( pVosContext, &setKey);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303648
Jeff Johnson295189b2012-06-20 16:38:30 -07003649 if ( status != eHAL_STATUS_SUCCESS )
3650 {
3651 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3652 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3653 __LINE__, status );
3654 }
3655 }
3656 }
3657 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303658 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003659 )
3660 {
3661 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3662
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303663 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3664
3665 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07003666 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303667 __func__, setKey.peerMac[0], setKey.peerMac[1],
3668 setKey.peerMac[2], setKey.peerMac[3],
Jeff Johnson295189b2012-06-20 16:38:30 -07003669 setKey.peerMac[4], setKey.peerMac[5]);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303670 if(pAdapter->sessionCtx.station.conn_info.connState ==
3671 eConnectionState_Associated)
Jeff Johnson295189b2012-06-20 16:38:30 -07003672 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303673 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07003674 pAdapter->sessionId, &setKey, &roamId );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303675
Jeff Johnson295189b2012-06-20 16:38:30 -07003676 if ( 0 != status )
3677 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303678 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003679 "%s: sme_RoamSetKey failure, returned %d",
3680 __func__, status);
3681 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3682 return -EINVAL;
3683 }
3684 }
3685 }
3686#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003687 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003688 return status;
3689}
3690
3691/*
3692 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3693 * This function is used to set the default tx key index
3694 */
3695#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3696static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3697 struct net_device *ndev,
3698 u8 key_index,
3699 bool unicast, bool multicast)
3700#else
3701static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3702 struct net_device *ndev,
3703 u8 key_index)
3704#endif
3705{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303706 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303707 int status;
Gopichand Nakkala29149562013-05-10 21:43:41 +05303708 hdd_wext_state_t *pWextState;
3709 hdd_station_ctx_t *pHddStaCtx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303710 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003711
3712 ENTER();
3713
Gopichand Nakkala29149562013-05-10 21:43:41 +05303714 if ((NULL == pAdapter))
3715 {
3716 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3717 "invalid adapter");
3718 return -EINVAL;
3719 }
3720
3721 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3722 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3723
3724 if ((NULL == pWextState) || (NULL == pHddStaCtx))
3725 {
3726 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3727 "invalid Wext state or HDD context");
3728 return -EINVAL;
3729 }
3730
Jeff Johnson295189b2012-06-20 16:38:30 -07003731 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3732 __func__,pAdapter->device_mode, key_index);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303733
Jeff Johnson295189b2012-06-20 16:38:30 -07003734 if (CSR_MAX_NUM_KEY <= key_index)
3735 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303736 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003737 key_index);
3738
3739 return -EINVAL;
3740 }
3741
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303742 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3743 status = wlan_hdd_validate_context(pHddCtx);
3744
3745 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003746 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303747 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3748 "%s: HDD context is not valid", __func__);
3749 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003750 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303751
Jeff Johnson295189b2012-06-20 16:38:30 -07003752 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003753 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303754 )
Jeff Johnson295189b2012-06-20 16:38:30 -07003755 {
Gopichand Nakkala29149562013-05-10 21:43:41 +05303756 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
Jeff Johnson295189b2012-06-20 16:38:30 -07003757 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303758 (eCSR_ENCRYPT_TYPE_AES !=
Jeff Johnson295189b2012-06-20 16:38:30 -07003759 pWextState->roamProfile.EncryptionType.encryptionType[0])
3760 )
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303761 {
3762 /* if default key index is not same as previous one,
Jeff Johnson295189b2012-06-20 16:38:30 -07003763 * then update the default key index */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303764
Jeff Johnson295189b2012-06-20 16:38:30 -07003765 tCsrRoamSetKey setKey;
3766 v_U32_t roamId= 0xFF;
3767 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303768
3769 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07003770 __func__, key_index);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303771
Jeff Johnson295189b2012-06-20 16:38:30 -07003772 Keys->defaultIndex = (u8)key_index;
3773 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3774 setKey.keyId = key_index;
3775 setKey.keyLength = Keys->KeyLength[key_index];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303776
3777 vos_mem_copy(&setKey.Key[0],
3778 &Keys->KeyMaterial[key_index][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07003779 Keys->KeyLength[key_index]);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303780
Gopichand Nakkala29149562013-05-10 21:43:41 +05303781 setKey.keyDirection = eSIR_TX_RX;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303782
3783 vos_mem_copy(setKey.peerMac,
Jeff Johnson295189b2012-06-20 16:38:30 -07003784 &pHddStaCtx->conn_info.bssId[0],
3785 WNI_CFG_BSSID_LEN);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303786
Gopichand Nakkala29149562013-05-10 21:43:41 +05303787 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
3788 pWextState->roamProfile.EncryptionType.encryptionType[0] ==
3789 eCSR_ENCRYPT_TYPE_WEP104)
3790 {
3791 /*In the case of dynamic wep supplicant hardcodes DWEP type to eCSR_ENCRYPT_TYPE_WEP104
3792 even though ap is configured for WEP-40 encryption. In this canse the key length
3793 is 5 but the encryption type is 104 hence checking the key langht(5) and encryption
3794 type(104) and switching encryption type to 40*/
3795 pWextState->roamProfile.EncryptionType.encryptionType[0] =
3796 eCSR_ENCRYPT_TYPE_WEP40;
3797 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
3798 eCSR_ENCRYPT_TYPE_WEP40;
3799 }
3800
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303801 setKey.encType =
Jeff Johnson295189b2012-06-20 16:38:30 -07003802 pWextState->roamProfile.EncryptionType.encryptionType[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303803
Jeff Johnson295189b2012-06-20 16:38:30 -07003804 /* issue set key request */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303805 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07003806 pAdapter->sessionId, &setKey, &roamId );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303807
Jeff Johnson295189b2012-06-20 16:38:30 -07003808 if ( 0 != status )
3809 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303810 hddLog(VOS_TRACE_LEVEL_ERROR,
3811 "%s: sme_RoamSetKey failed, returned %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003812 status);
3813 return -EINVAL;
3814 }
3815 }
3816 }
3817
3818 /* In SoftAp mode setting key direction for default mode */
3819 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3820 {
3821 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3822 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3823 (eCSR_ENCRYPT_TYPE_AES !=
3824 pWextState->roamProfile.EncryptionType.encryptionType[0])
3825 )
3826 {
3827 /* Saving key direction for default key index to TX default */
3828 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3829 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3830 }
3831 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303832
Jeff Johnson295189b2012-06-20 16:38:30 -07003833 return status;
3834}
3835
Jeff Johnson295189b2012-06-20 16:38:30 -07003836/*
3837 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3838 * This function is used to inform the BSS details to nl80211 interface.
3839 */
3840static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3841 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3842{
3843 struct net_device *dev = pAdapter->dev;
3844 struct wireless_dev *wdev = dev->ieee80211_ptr;
3845 struct wiphy *wiphy = wdev->wiphy;
3846 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3847 int chan_no;
3848 int ie_length;
3849 const char *ie;
3850 unsigned int freq;
3851 struct ieee80211_channel *chan;
3852 int rssi = 0;
3853 struct cfg80211_bss *bss = NULL;
3854
3855 ENTER();
3856
3857 if( NULL == pBssDesc )
3858 {
3859 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3860 return bss;
3861 }
3862
3863 chan_no = pBssDesc->channelId;
3864 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3865 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3866
3867 if( NULL == ie )
3868 {
3869 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3870 return bss;
3871 }
3872
3873#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3874 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3875 {
3876 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3877 }
3878 else
3879 {
3880 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3881 }
3882#else
3883 freq = ieee80211_channel_to_frequency(chan_no);
3884#endif
3885
3886 chan = __ieee80211_get_channel(wiphy, freq);
3887
3888 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3889 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3890 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3891 if (bss == NULL)
3892 {
3893 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3894
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303895 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3896 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
Jeff Johnson295189b2012-06-20 16:38:30 -07003897 pBssDesc->capabilityInfo,
3898 pBssDesc->beaconInterval, ie, ie_length,
3899 rssi, GFP_KERNEL ));
3900}
3901 else
3902 {
3903 return bss;
3904 }
3905}
3906
3907
3908
3909/*
3910 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3911 * This function is used to inform the BSS details to nl80211 interface.
3912 */
3913struct cfg80211_bss*
3914wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3915 tSirBssDescription *bss_desc
3916 )
3917{
3918 /*
3919 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3920 already exists in bss data base of cfg80211 for that particular BSS ID.
3921 Using cfg80211_inform_bss_frame to update the bss entry instead of
3922 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3923 now there is no possibility to get the mgmt(probe response) frame from PE,
3924 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3925 cfg80211_inform_bss_frame.
3926 */
3927 struct net_device *dev = pAdapter->dev;
3928 struct wireless_dev *wdev = dev->ieee80211_ptr;
3929 struct wiphy *wiphy = wdev->wiphy;
3930 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003931#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3932 qcom_ie_age *qie_age = NULL;
3933 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3934#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003935 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003936#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003937 const char *ie =
3938 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3939 unsigned int freq;
3940 struct ieee80211_channel *chan;
3941 struct ieee80211_mgmt *mgmt =
3942 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3943 struct cfg80211_bss *bss_status = NULL;
3944 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3945 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003946#ifdef WLAN_OPEN_SOURCE
3947 struct timespec ts;
3948#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003949
3950 ENTER();
3951
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003952 if (!mgmt)
3953 return NULL;
3954
Jeff Johnson295189b2012-06-20 16:38:30 -07003955 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003956
3957#ifdef WLAN_OPEN_SOURCE
3958 /* Android does not want the timestamp from the frame.
3959 Instead it wants a monotonic increasing value */
3960 get_monotonic_boottime(&ts);
3961 mgmt->u.probe_resp.timestamp =
3962 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3963#else
3964 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003965 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3966 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003967
3968#endif
3969
Jeff Johnson295189b2012-06-20 16:38:30 -07003970 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3971 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003972
3973#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3974 /* GPS Requirement: need age ie per entry. Using vendor specific. */
3975 /* Assuming this is the last IE, copy at the end */
3976 ie_length -=sizeof(qcom_ie_age);
3977 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
3978 qie_age->element_id = QCOM_VENDOR_IE_ID;
3979 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
3980 qie_age->oui_1 = QCOM_OUI1;
3981 qie_age->oui_2 = QCOM_OUI2;
3982 qie_age->oui_3 = QCOM_OUI3;
3983 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
3984 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
3985#endif
3986
Jeff Johnson295189b2012-06-20 16:38:30 -07003987 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
Gopichand Nakkalad908ec82013-05-16 19:32:19 +05303988 if (bss_desc->fProbeRsp)
3989 {
3990 mgmt->frame_control |=
3991 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3992 }
3993 else
3994 {
3995 mgmt->frame_control |=
3996 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
3997 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003998
3999#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304000 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07004001 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
4002 {
4003 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
4004 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304005 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07004006 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
4007
4008 {
4009 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
4010 }
4011 else
4012 {
4013 kfree(mgmt);
4014 return NULL;
4015 }
4016#else
4017 freq = ieee80211_channel_to_frequency(chan_no);
4018#endif
4019 chan = __ieee80211_get_channel(wiphy, freq);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08004020 /*when the band is changed on the fly using the GUI, three things are done
4021 * 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)
4022 * as part of the scan abort, message willbe queued to PE and we proceed with flushing and changinh the band.
4023 * pe will stop the scanning further and report back the results what ever it had till now by calling the call back function.
4024 * if the time between update band and scandone call back is sufficent enough the band change reflects in SME, SME validates the channels
4025 * and discards the channels correponding to previous band and calls back with zero bss results.
4026 * 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
4027 * all the channels correponding to previous band.this is due to race condition.but those channels are invalid to the new band and so
4028 * this function __ieee80211_get_channel will return NULL.Each time we report scan result with this pointer null warning kernel trace is printed.
4029 * if the scan results contain large number of APs continuosly kernel warning trace is printed and it will lead to apps watch dog bark.
4030 * So drop the bss and continue to next bss.
4031 */
4032 if(chan == NULL)
4033 {
4034 hddLog(VOS_TRACE_LEVEL_INFO, "%s chan pointer is NULL", __func__);
Chilam Ngc4244af2013-04-01 15:37:32 -07004035 kfree(mgmt);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08004036 return NULL;
4037 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004038 /*To keep the rssi icon of the connected AP in the scan window
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304039 *and the rssi icon of the wireless networks in sync
Jeff Johnson295189b2012-06-20 16:38:30 -07004040 * */
4041 if (( eConnectionState_Associated ==
4042 pAdapter->sessionCtx.station.conn_info.connState ) &&
4043 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
4044 pAdapter->sessionCtx.station.conn_info.bssId,
4045 WNI_CFG_BSSID_LEN)))
4046 {
4047 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
4048 rssi = (pAdapter->rssi * 100);
4049 }
4050 else
4051 {
4052 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
4053 }
4054
4055 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
4056 frame_len, rssi, GFP_KERNEL);
4057 kfree(mgmt);
4058 return bss_status;
4059}
4060
4061/*
4062 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
4063 * This function is used to update the BSS data base of CFG8011
4064 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304065struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07004066 tCsrRoamInfo *pRoamInfo
4067 )
4068{
4069 tCsrRoamConnectedProfile roamProfile;
4070 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4071 struct cfg80211_bss *bss = NULL;
4072
4073 ENTER();
4074
4075 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
4076 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
4077
4078 if (NULL != roamProfile.pBssDesc)
4079 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304080 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07004081 &roamProfile);
4082
4083 if (NULL == bss)
4084 {
4085 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
4086 __func__);
4087 }
4088
4089 sme_RoamFreeConnectProfile(hHal, &roamProfile);
4090 }
4091 else
4092 {
4093 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
4094 __func__);
4095 }
4096 return bss;
4097}
4098
4099/*
4100 * FUNCTION: wlan_hdd_cfg80211_update_bss
4101 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304102static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
4103 hdd_adapter_t *pAdapter
Jeff Johnson295189b2012-06-20 16:38:30 -07004104 )
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304105{
Jeff Johnson295189b2012-06-20 16:38:30 -07004106 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4107 tCsrScanResultInfo *pScanResult;
4108 eHalStatus status = 0;
4109 tScanResultHandle pResult;
4110 struct cfg80211_bss *bss_status = NULL;
4111
4112 ENTER();
4113
4114 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4115 {
4116 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
4117 return -EAGAIN;
4118 }
4119
4120 /*
4121 * start getting scan results and populate cgf80211 BSS database
4122 */
4123 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
4124
4125 /* no scan results */
4126 if (NULL == pResult)
4127 {
4128 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
4129 return status;
4130 }
4131
4132 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
4133
4134 while (pScanResult)
4135 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304136 /*
4137 * cfg80211_inform_bss() is not updating ie field of bss entry, if
4138 * entry already exists in bss data base of cfg80211 for that
4139 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
4140 * bss entry instead of cfg80211_inform_bss, But this call expects
4141 * mgmt packet as input. As of now there is no possibility to get
4142 * the mgmt(probe response) frame from PE, converting bss_desc to
Jeff Johnson295189b2012-06-20 16:38:30 -07004143 * ieee80211_mgmt(probe response) and passing to c
4144 * fg80211_inform_bss_frame.
4145 * */
4146
4147 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
4148 &pScanResult->BssDescriptor);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304149
Jeff Johnson295189b2012-06-20 16:38:30 -07004150
4151 if (NULL == bss_status)
4152 {
4153 hddLog(VOS_TRACE_LEVEL_INFO,
4154 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
4155 }
4156 else
4157 {
Yue Maf49ba872013-08-19 12:04:25 -07004158 cfg80211_put_bss(
4159#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
4160 wiphy,
4161#endif
4162 bss_status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004163 }
4164
4165 pScanResult = sme_ScanResultGetNext(hHal, pResult);
4166 }
4167
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304168 sme_ScanResultPurge(hHal, pResult);
Jeff Johnson295189b2012-06-20 16:38:30 -07004169
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304170 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004171}
4172
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004173void
4174hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
4175{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304176 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004177 "%02X:%02X:%02X:%02X:%02X:%02X\n",
4178 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
4179 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004180} /****** end hddPrintMacAddr() ******/
4181
4182void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004183hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004184{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304185 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004186 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
4187 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
4188 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
4189 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004190} /****** end hddPrintPmkId() ******/
4191
4192//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
4193//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
4194
4195//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
4196//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
4197
4198#define dump_bssid(bssid) \
4199 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004200 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
4201 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
4202 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004203 }
4204
4205#define dump_pmkid(pMac, pmkid) \
4206 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004207 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
4208 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
4209 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004210 }
4211
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07004212#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004213/*
4214 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
4215 * This function is used to notify the supplicant of a new PMKSA candidate.
4216 */
4217int wlan_hdd_cfg80211_pmksa_candidate_notify(
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304218 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004219 int index, bool preauth )
4220{
Jeff Johnsone7245742012-09-05 17:12:55 -07004221#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004222 struct net_device *dev = pAdapter->dev;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004223 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004224
4225 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07004226 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004227
4228 if( NULL == pRoamInfo )
4229 {
4230 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
4231 return -EINVAL;
4232 }
4233
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004234 if (eANI_BOOLEAN_TRUE == hdd_is_okc_mode_enabled(pHddCtx))
4235 {
4236 dump_bssid(pRoamInfo->bssid);
4237 cfg80211_pmksa_candidate_notify(dev, index,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004238 pRoamInfo->bssid, preauth, GFP_KERNEL);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004239 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004240#endif /* FEATURE_WLAN_OKC */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304241 return 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004242}
4243#endif //FEATURE_WLAN_LFR
4244
Jeff Johnson295189b2012-06-20 16:38:30 -07004245/*
4246 * FUNCTION: hdd_cfg80211_scan_done_callback
4247 * scanning callback function, called after finishing scan
4248 *
4249 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304250static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
Jeff Johnson295189b2012-06-20 16:38:30 -07004251 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
4252{
4253 struct net_device *dev = (struct net_device *) pContext;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304254 //struct wireless_dev *wdev = dev->ieee80211_ptr;
Jeff Johnson295189b2012-06-20 16:38:30 -07004255 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004256 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4257 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004258 struct cfg80211_scan_request *req = NULL;
4259 int ret = 0;
4260
4261 ENTER();
4262
4263 hddLog(VOS_TRACE_LEVEL_INFO,
4264 "%s called with halHandle = %p, pContext = %p,"
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304265 "scanID = %d, returned status = %d\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07004266 __func__, halHandle, pContext, (int) scanId, (int) status);
4267
4268 //Block on scan req completion variable. Can't wait forever though.
4269 ret = wait_for_completion_interruptible_timeout(
4270 &pScanInfo->scan_req_completion_event,
4271 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
4272 if (!ret)
4273 {
4274 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004275 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004276 }
4277
4278 if(pScanInfo->mScanPending != VOS_TRUE)
4279 {
4280 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004281 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004282 }
4283
4284 /* Check the scanId */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304285 if (pScanInfo->scanId != scanId)
Jeff Johnson295189b2012-06-20 16:38:30 -07004286 {
4287 hddLog(VOS_TRACE_LEVEL_INFO,
4288 "%s called with mismatched scanId pScanInfo->scanId = %d "
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304289 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
Jeff Johnson295189b2012-06-20 16:38:30 -07004290 (int) scanId);
4291 }
4292
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304293 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07004294 pAdapter);
4295
4296 if (0 > ret)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304297 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004298
4299
4300 /* If any client wait scan result through WEXT
4301 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004302 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07004303 {
4304 /* The other scan request waiting for current scan finish
4305 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004306 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004307 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004308 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004309 }
4310 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004311 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004312 {
4313 struct net_device *dev = pAdapter->dev;
4314 union iwreq_data wrqu;
4315 int we_event;
4316 char *msg;
4317
4318 memset(&wrqu, '\0', sizeof(wrqu));
4319 we_event = SIOCGIWSCAN;
4320 msg = NULL;
4321 wireless_send_event(dev, we_event, &wrqu, msg);
4322 }
4323 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004324 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004325
4326 /* Get the Scan Req */
4327 req = pAdapter->request;
4328
4329 if (!req)
4330 {
4331 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004332 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07004333 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004334 }
4335
4336 /*
4337 * setting up 0, just in case.
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304338 */
Jeff Johnson295189b2012-06-20 16:38:30 -07004339 req->n_ssids = 0;
4340 req->n_channels = 0;
4341 req->ie = 0;
4342
Jeff Johnson295189b2012-06-20 16:38:30 -07004343 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004344 /* Scan is no longer pending */
4345 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004346
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07004347 /*
4348 * cfg80211_scan_done informing NL80211 about completion
4349 * of scanning
4350 */
4351 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004352 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004353
Jeff Johnsone7245742012-09-05 17:12:55 -07004354allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004355 /* release the wake lock at the end of the scan*/
4356 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004357
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004358 /* Acquire wakelock to handle the case where APP's tries to suspend
4359 * immediatly after the driver gets connect request(i.e after scan)
4360 * from supplicant, this result in app's is suspending and not able
4361 * to process the connect request to AP */
Amar Singhal6144c002013-05-03 16:11:42 -07004362 hdd_allow_suspend_timeout(1000);
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004363
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004364#ifdef FEATURE_WLAN_TDLS
4365 wlan_hdd_tdls_scan_done_callback(pAdapter);
4366#endif
4367
Jeff Johnson295189b2012-06-20 16:38:30 -07004368 EXIT();
4369 return 0;
4370}
4371
4372/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004373 * FUNCTION: hdd_isScanAllowed
4374 * Go through each adapter and check if scan allowed
4375 *
4376 */
4377v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
4378{
4379 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4380 hdd_station_ctx_t *pHddStaCtx = NULL;
4381 hdd_adapter_t *pAdapter = NULL;
4382 VOS_STATUS status = 0;
4383 v_U8_t staId = 0;
4384 v_U8_t *staMac = NULL;
4385
4386 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4387
4388 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4389 {
4390 pAdapter = pAdapterNode->pAdapter;
4391
4392 if( pAdapter )
4393 {
4394 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304395 "%s: Adapter with device mode %d exists",
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004396 __func__, pAdapter->device_mode);
4397 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4398 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4399 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
4400 {
4401 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4402 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
4403 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
4404 {
4405 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
4406 hddLog(VOS_TRACE_LEVEL_ERROR,
4407 "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the "
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304408 "middle of WPS/EAPOL exchange.", __func__,
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004409 staMac[0], staMac[1], staMac[2],
4410 staMac[3], staMac[4], staMac[5]);
4411 return VOS_FALSE;
4412 }
4413 }
4414 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
4415 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
4416 {
4417 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
4418 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304419 if ((pAdapter->aStaInfo[staId].isUsed) &&
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004420 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
4421 {
4422 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
4423
4424 hddLog(VOS_TRACE_LEVEL_ERROR,
4425 "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the "
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304426 "middle of WPS/EAPOL exchange.", __func__,
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004427 staMac[0], staMac[1], staMac[2],
4428 staMac[3], staMac[4], staMac[5]);
4429 return VOS_FALSE;
4430 }
4431 }
4432 }
4433 }
4434 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4435 pAdapterNode = pNext;
4436 }
4437 hddLog(VOS_TRACE_LEVEL_INFO,
4438 "%s: Scan allowed", __func__);
4439 return VOS_TRUE;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304440}
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004441
4442/*
Jeff Johnson295189b2012-06-20 16:38:30 -07004443 * FUNCTION: wlan_hdd_cfg80211_scan
4444 * this scan respond to scan trigger and update cfg80211 scan database
4445 * later, scan dump command can be used to recieve scan results
4446 */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08004447int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
4448#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4449 struct net_device *dev,
4450#endif
4451 struct cfg80211_scan_request *request)
4452{
4453#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4454 struct net_device *dev = request->wdev->netdev;
4455#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304456 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07004457 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4458 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304459 hdd_config_t *cfg_param = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004460 tCsrScanRequest scanRequest;
4461 tANI_U8 *channelList = NULL, i;
4462 v_U32_t scanId = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304463 int status;
4464 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004465 v_U8_t* pP2pIe = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004466
4467 ENTER();
4468
4469 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4470 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004471
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304472 status = wlan_hdd_validate_context(pHddCtx);
4473
4474 if (0 != status)
4475 {
4476 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4477 "%s: HDD context is not valid", __func__);
4478 return status;
4479 }
4480
4481 cfg_param = pHddCtx->cfg_ini;
4482 pScanInfo = &pHddCtx->scan_info;
4483
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004484 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004485 (eConnectionState_Connecting ==
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004486 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004487 {
4488 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004489 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
4490 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004491 return -EBUSY;
4492 }
4493
Jeff Johnson295189b2012-06-20 16:38:30 -07004494#ifdef WLAN_BTAMP_FEATURE
4495 //Scan not supported when AMP traffic is on.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004496 if (VOS_TRUE == WLANBAP_AmpSessionOn())
Jeff Johnson295189b2012-06-20 16:38:30 -07004497 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004498 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004499 "%s: No scanning when AMP is on", __func__);
4500 return -EOPNOTSUPP;
4501 }
4502#endif
4503 //Scan on any other interface is not supported.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004504 if (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07004505 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004506 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004507 "%s: Not scanning on device_mode = %d",
4508 __func__, pAdapter->device_mode);
4509 return -EOPNOTSUPP;
4510 }
4511
4512 if (TRUE == pScanInfo->mScanPending)
4513 {
4514 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004515 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07004516 }
4517
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304518 //Don't Allow Scan and return busy if Remain On
Jeff Johnson32d95a32012-09-10 13:15:23 -07004519 //Channel and action frame is pending
4520 //Otherwise Cancel Remain On Channel and allow Scan
4521 //If no action frame pending
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004522 if (0 != wlan_hdd_check_remain_on_channel(pAdapter))
Jeff Johnson32d95a32012-09-10 13:15:23 -07004523 {
4524 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
4525 return -EBUSY;
4526 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004527#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004528 /* if tdls disagree scan right now, return immediately.
4529 tdls will schedule the scan when scan is allowed. (return SUCCESS)
4530 or will reject the scan if any TDLS is in progress. (return -EBUSY)
4531 */
4532 status = wlan_hdd_tdls_scan_callback (pAdapter,
4533 wiphy,
4534#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4535 dev,
Gopichand Nakkalac3c42b92013-03-20 19:42:34 -07004536#endif
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004537 request);
4538 if(status <= 0)
4539 {
4540 hddLog(VOS_TRACE_LEVEL_INFO, "%s: TDLS Pending %d", __func__, status);
4541 return status;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004542 }
4543#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07004544
Jeff Johnson295189b2012-06-20 16:38:30 -07004545 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
4546 {
4547 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08004548 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004549 return -EAGAIN;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304550 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004551 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
4552 {
4553 hddLog(VOS_TRACE_LEVEL_WARN,
4554 "%s: MAX TM Level Scan not allowed", __func__);
4555 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304556 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07004557 }
4558 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4559
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004560 /* Check if scan is allowed at this point of time.
4561 */
4562 if (!hdd_isScanAllowed(pHddCtx))
4563 {
4564 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
4565 return -EBUSY;
4566 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304567
Jeff Johnson295189b2012-06-20 16:38:30 -07004568 vos_mem_zero( &scanRequest, sizeof(scanRequest));
4569
4570 if (NULL != request)
4571 {
4572 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304573 (int)request->n_ssids);
Jeff Johnson295189b2012-06-20 16:38:30 -07004574
4575 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
4576 * Becasue of this, driver is assuming that this is not wildcard scan and so
4577 * is not aging out the scan results.
4578 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07004579 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07004580 {
4581 request->n_ssids = 0;
4582 }
4583
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004584 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07004585 {
4586 tCsrSSIDInfo *SsidInfo;
4587 int j;
4588 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
4589 /* Allocate num_ssid tCsrSSIDInfo structure */
4590 SsidInfo = scanRequest.SSIDs.SSIDList =
4591 ( tCsrSSIDInfo *)vos_mem_malloc(
4592 request->n_ssids*sizeof(tCsrSSIDInfo));
4593
4594 if(NULL == scanRequest.SSIDs.SSIDList)
4595 {
4596 hddLog(VOS_TRACE_LEVEL_ERROR,
4597 "memory alloc failed SSIDInfo buffer");
4598 return -ENOMEM;
4599 }
4600
4601 /* copy all the ssid's and their length */
4602 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
4603 {
4604 /* get the ssid length */
4605 SsidInfo->SSID.length = request->ssids[j].ssid_len;
4606 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
4607 SsidInfo->SSID.length);
4608 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
4609 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
4610 j, SsidInfo->SSID.ssId);
4611 }
4612 /* set the scan type to active */
4613 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4614 }
4615 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4616 {
4617 /* set the scan type to active */
4618 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4619 }
4620 else
4621 {
4622 /*Set the scan type to default type, in this case it is ACTIVE*/
4623 scanRequest.scanType = pScanInfo->scan_mode;
4624 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304625 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
Jeff Johnson295189b2012-06-20 16:38:30 -07004626 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4627 }
4628 else
4629 {
4630 /* set the scan type to active */
4631 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4632 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4633
4634 /* set min and max channel time to zero */
4635 scanRequest.minChnTime = 0;
4636 scanRequest.maxChnTime = 0;
4637 }
4638
4639 /* set BSSType to default type */
4640 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4641
4642 /*TODO: scan the requested channels only*/
4643
4644 /*Right now scanning all the channels */
4645 if( request )
4646 {
4647 if( request->n_channels )
4648 {
4649 channelList = vos_mem_malloc( request->n_channels );
4650 if( NULL == channelList )
4651 {
4652 status = -ENOMEM;
4653 goto free_mem;
4654 }
4655
4656 for( i = 0 ; i < request->n_channels ; i++ )
4657 channelList[i] = request->channels[i]->hw_value;
4658 }
4659
4660 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4661 scanRequest.ChannelInfo.ChannelList = channelList;
4662
4663 /* set requestType to full scan */
4664 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304665
4666 /* Flush the scan results(only p2p beacons) for STA scan and P2P
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004667 * search (Flush on both full scan and social scan but not on single
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304668 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004669 */
4670
4671 /* Supplicant does single channel scan after 8-way handshake
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304672 * and in that case driver shoudnt flush scan results. If
4673 * driver flushes the scan results here and unfortunately if
4674 * the AP doesnt respond to our probe req then association
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004675 * fails which is not desired
4676 */
4677
4678 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4679 {
4680 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4681 pAdapter->sessionId );
4682 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004683
4684 if( request->ie_len )
4685 {
4686 /* save this for future association (join requires this) */
4687 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4688 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4689 pScanInfo->scanAddIE.length = request->ie_len;
4690
4691 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004692 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4693 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004694 )
4695 {
4696 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4697 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4698 }
4699
4700 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4701 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4702
Jeff Johnson295189b2012-06-20 16:38:30 -07004703 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4704 request->ie_len);
4705 if (pP2pIe != NULL)
4706 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004707#ifdef WLAN_FEATURE_P2P_DEBUG
4708 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4709 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4710 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4711 {
4712 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4713 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4714 "Go nego completed to Connection is started");
4715 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4716 "for 8way Handshake");
4717 }
4718 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4719 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4720 {
4721 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4722 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4723 "Disconnected state to Connection is started");
4724 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4725 "for 4way Handshake");
4726 }
4727#endif
4728
Jeff Johnsone7245742012-09-05 17:12:55 -07004729 /* no_cck will be set during p2p find to disable 11b rates */
4730 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004731 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004732 hddLog(VOS_TRACE_LEVEL_INFO,
4733 "%s: This is a P2P Search", __func__);
4734 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004735
Jeff Johnsone7245742012-09-05 17:12:55 -07004736 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4737 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004738 /* set requestType to P2P Discovery */
4739 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004740 }
4741
4742 /*
4743 Skip Dfs Channel in case of P2P Search
4744 if it is set in ini file
4745 */
4746 if(cfg_param->skipDfsChnlInP2pSearch)
4747 {
4748 scanRequest.skipDfsChnlInP2pSearch = 1;
4749 }
4750 else
4751 {
4752 scanRequest.skipDfsChnlInP2pSearch = 0;
4753 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004754
Jeff Johnson295189b2012-06-20 16:38:30 -07004755 }
4756 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004757 }
4758 }
4759
4760 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4761
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004762 /* acquire the wakelock to avoid the apps suspend during the scan. To
4763 * address the following issues.
4764 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4765 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4766 * for long time, this result in apps running at full power for long time.
4767 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4768 * be stuck in full power because of resume BMPS
4769 */
4770 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004771
4772 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004773 pAdapter->sessionId, &scanRequest, &scanId,
4774 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004775
Jeff Johnson295189b2012-06-20 16:38:30 -07004776 if (eHAL_STATUS_SUCCESS != status)
4777 {
4778 hddLog(VOS_TRACE_LEVEL_ERROR,
4779 "%s: sme_ScanRequest returned error %d", __func__, status);
4780 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004781 if(eHAL_STATUS_RESOURCES == status)
4782 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004783 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 -07004784 status = -EBUSY;
4785 } else {
4786 status = -EIO;
4787 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004788 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004789 goto free_mem;
4790 }
4791
4792 pScanInfo->mScanPending = TRUE;
4793 pAdapter->request = request;
4794 pScanInfo->scanId = scanId;
4795
4796 complete(&pScanInfo->scan_req_completion_event);
4797
4798free_mem:
4799 if( scanRequest.SSIDs.SSIDList )
4800 {
4801 vos_mem_free(scanRequest.SSIDs.SSIDList);
4802 }
4803
4804 if( channelList )
4805 vos_mem_free( channelList );
4806
4807 EXIT();
4808
4809 return status;
4810}
4811
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07004812
4813void hdd_select_cbmode( hdd_adapter_t *pAdapter,v_U8_t operationChannel)
4814{
4815 v_U8_t iniDot11Mode =
4816 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->dot11Mode;
4817 eHddDot11Mode hddDot11Mode = iniDot11Mode;
4818
4819 switch ( iniDot11Mode )
4820 {
4821 case eHDD_DOT11_MODE_AUTO:
4822 case eHDD_DOT11_MODE_11ac:
4823 case eHDD_DOT11_MODE_11ac_ONLY:
4824#ifdef WLAN_FEATURE_11AC
4825 hddDot11Mode = eHDD_DOT11_MODE_11ac;
4826#else
4827 hddDot11Mode = eHDD_DOT11_MODE_11n;
4828#endif
4829 break;
4830 case eHDD_DOT11_MODE_11n:
4831 case eHDD_DOT11_MODE_11n_ONLY:
4832 hddDot11Mode = eHDD_DOT11_MODE_11n;
4833 break;
4834 default:
4835 hddDot11Mode = iniDot11Mode;
4836 break;
4837 }
4838 /* This call decides required channel bonding mode */
4839 sme_SelectCBMode((WLAN_HDD_GET_CTX(pAdapter)->hHal),
4840 hdd_cfg_xlate_to_csr_phy_mode(hddDot11Mode),
4841 operationChannel);
4842}
4843
Jeff Johnson295189b2012-06-20 16:38:30 -07004844/*
4845 * FUNCTION: wlan_hdd_cfg80211_connect_start
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304846 * This function is used to start the association process
Jeff Johnson295189b2012-06-20 16:38:30 -07004847 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304848int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004849 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004850{
4851 int status = 0;
4852 hdd_wext_state_t *pWextState;
4853 v_U32_t roamId;
4854 tCsrRoamProfile *pRoamProfile;
4855 eMib_dot11DesiredBssType connectedBssType;
4856 eCsrAuthType RSNAuthType;
4857
4858 ENTER();
4859
4860 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304861
Jeff Johnson295189b2012-06-20 16:38:30 -07004862 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4863 {
4864 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4865 return -EINVAL;
4866 }
4867
4868 pRoamProfile = &pWextState->roamProfile;
4869
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304870 if (pRoamProfile)
Jeff Johnson295189b2012-06-20 16:38:30 -07004871 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004872 int ret = 0;
4873 hdd_station_ctx_t *pHddStaCtx;
4874 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4875 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4876
4877 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4878 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4879 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004880 {
4881 /* Issue disconnect to CSR */
4882 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304883 if( eHAL_STATUS_SUCCESS ==
Jeff Johnson295189b2012-06-20 16:38:30 -07004884 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4885 pAdapter->sessionId,
4886 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4887 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004888 ret = wait_for_completion_interruptible_timeout(
4889 &pAdapter->disconnect_comp_var,
4890 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4891 if (0 == ret)
4892 {
4893 VOS_ASSERT(0);
4894 }
4895 }
4896 }
4897 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4898 {
4899 ret = wait_for_completion_interruptible_timeout(
4900 &pAdapter->disconnect_comp_var,
4901 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4902 if (0 == ret)
4903 {
4904 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004905 }
4906 }
4907
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304908 if (HDD_WMM_USER_MODE_NO_QOS ==
Jeff Johnson295189b2012-06-20 16:38:30 -07004909 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4910 {
4911 /*QoS not enabled in cfg file*/
4912 pRoamProfile->uapsd_mask = 0;
4913 }
4914 else
4915 {
4916 /*QoS enabled, update uapsd mask from cfg file*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304917 pRoamProfile->uapsd_mask =
Jeff Johnson295189b2012-06-20 16:38:30 -07004918 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4919 }
4920
4921 pRoamProfile->SSIDs.numOfSSIDs = 1;
4922 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4923 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304924 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Jeff Johnson295189b2012-06-20 16:38:30 -07004925 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4926 ssid, ssid_len);
4927
4928 if (bssid)
4929 {
4930 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4931 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4932 WNI_CFG_BSSID_LEN);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304933 /* Save BSSID in seperate variable as well, as RoamProfile
4934 BSSID is getting zeroed out in the association process. And in
Jeff Johnson295189b2012-06-20 16:38:30 -07004935 case of join failure we should send valid BSSID to supplicant
4936 */
4937 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4938 WNI_CFG_BSSID_LEN);
4939 }
Dhanashri Atre51981c62013-06-13 11:47:57 -07004940 else
4941 {
4942 vos_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),WNI_CFG_BSSID_LEN);
4943 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004944
4945 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4946 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304947 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004948 /*set gen ie*/
4949 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4950 /*set auth*/
4951 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4952 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004953#ifdef FEATURE_WLAN_WAPI
4954 if (pAdapter->wapi_info.nWapiMode)
4955 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004956 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004957 switch (pAdapter->wapi_info.wapiAuthMode)
4958 {
4959 case WAPI_AUTH_MODE_PSK:
4960 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004961 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004962 pAdapter->wapi_info.wapiAuthMode);
4963 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4964 break;
4965 }
4966 case WAPI_AUTH_MODE_CERT:
4967 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004968 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004969 pAdapter->wapi_info.wapiAuthMode);
4970 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4971 break;
4972 }
4973 } // End of switch
4974 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4975 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4976 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004977 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004978 pRoamProfile->AuthType.numEntries = 1;
4979 pRoamProfile->EncryptionType.numEntries = 1;
4980 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4981 pRoamProfile->mcEncryptionType.numEntries = 1;
4982 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4983 }
4984 }
4985#endif /* FEATURE_WLAN_WAPI */
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05304986#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05304987 /* Initializing gtkOffloadReqParams */
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05304988 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4989 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4990 {
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05304991 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
4992 sizeof (tSirGtkOffloadParams));
4993 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05304994 }
4995#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004996 pRoamProfile->csrPersona = pAdapter->device_mode;
4997
Jeff Johnson32d95a32012-09-10 13:15:23 -07004998 if( operatingChannel )
4999 {
5000 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
5001 pRoamProfile->ChannelInfo.numOfChannels = 1;
5002 }
Chet Lanctot186b5732013-03-18 10:26:30 -07005003 else
5004 {
5005 pRoamProfile->ChannelInfo.ChannelList = NULL;
5006 pRoamProfile->ChannelInfo.numOfChannels = 0;
5007 }
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07005008 if ( (WLAN_HDD_IBSS == pAdapter->device_mode) && operatingChannel)
5009 {
5010 hdd_select_cbmode(pAdapter,operatingChannel);
5011 }
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005012 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
5013 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305014 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005015 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08005016 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
5017 */
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305018 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
5019 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08005020 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
5021 eConnectionState_Connecting);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305022
5023 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07005024 pAdapter->sessionId, pRoamProfile, &roamId);
5025
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305026 if ((eHAL_STATUS_SUCCESS != status) &&
5027 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
5028 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05305029
5030 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005031 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
5032 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
5033 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05305034 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005035 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05305036 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08005037
5038 pRoamProfile->ChannelInfo.ChannelList = NULL;
5039 pRoamProfile->ChannelInfo.numOfChannels = 0;
5040
Jeff Johnson295189b2012-06-20 16:38:30 -07005041 }
5042 else
5043 {
5044 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
5045 return -EINVAL;
5046 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08005047 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005048 return status;
5049}
5050
5051/*
5052 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
5053 * This function is used to set the authentication type (OPEN/SHARED).
5054 *
5055 */
5056static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
5057 enum nl80211_auth_type auth_type)
5058{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305059 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005060 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5061
5062 ENTER();
5063
5064 /*set authentication type*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305065 switch (auth_type)
Jeff Johnson295189b2012-06-20 16:38:30 -07005066 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005067 case NL80211_AUTHTYPE_AUTOMATIC:
Gopichand Nakkala29149562013-05-10 21:43:41 +05305068 hddLog(VOS_TRACE_LEVEL_INFO,
5069 "%s: set authentication type to AUTOSWITCH", __func__);
5070 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
5071 break;
5072
5073 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07005074#ifdef WLAN_FEATURE_VOWIFI_11R
5075 case NL80211_AUTHTYPE_FT:
5076#endif /* WLAN_FEATURE_VOWIFI_11R */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305077 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07005078 "%s: set authentication type to OPEN", __func__);
5079 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5080 break;
5081
5082 case NL80211_AUTHTYPE_SHARED_KEY:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305083 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07005084 "%s: set authentication type to SHARED", __func__);
5085 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
5086 break;
5087#ifdef FEATURE_WLAN_CCX
5088 case NL80211_AUTHTYPE_NETWORK_EAP:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305089 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07005090 "%s: set authentication type to CCKM WPA", __func__);
5091 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
5092 break;
5093#endif
5094
5095
5096 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305097 hddLog(VOS_TRACE_LEVEL_ERROR,
5098 "%s: Unsupported authentication type %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07005099 auth_type);
5100 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
5101 return -EINVAL;
5102 }
5103
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305104 pWextState->roamProfile.AuthType.authType[0] =
Jeff Johnson295189b2012-06-20 16:38:30 -07005105 pHddStaCtx->conn_info.authType;
5106 return 0;
5107}
5108
5109/*
5110 * FUNCTION: wlan_hdd_set_akm_suite
5111 * This function is used to set the key mgmt type(PSK/8021x).
5112 *
5113 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305114static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07005115 u32 key_mgmt
5116 )
5117{
5118 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5119 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305120
Jeff Johnson295189b2012-06-20 16:38:30 -07005121 /*set key mgmt type*/
5122 switch(key_mgmt)
5123 {
5124 case WLAN_AKM_SUITE_PSK:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05305125#ifdef WLAN_FEATURE_VOWIFI_11R
5126 case WLAN_AKM_SUITE_FT_PSK:
5127#endif
5128 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
Jeff Johnson295189b2012-06-20 16:38:30 -07005129 __func__);
5130 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
5131 break;
5132
5133 case WLAN_AKM_SUITE_8021X:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05305134#ifdef WLAN_FEATURE_VOWIFI_11R
5135 case WLAN_AKM_SUITE_FT_8021X:
5136#endif
5137 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
Jeff Johnson295189b2012-06-20 16:38:30 -07005138 __func__);
5139 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
5140 break;
5141#ifdef FEATURE_WLAN_CCX
5142#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
5143#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
5144 case WLAN_AKM_SUITE_CCKM:
5145 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
5146 __func__);
5147 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
5148 break;
5149#endif
5150
5151 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305152 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005153 __func__, key_mgmt);
5154 return -EINVAL;
5155
5156 }
5157 return 0;
5158}
5159
5160/*
5161 * FUNCTION: wlan_hdd_cfg80211_set_cipher
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305162 * This function is used to set the encryption type
Jeff Johnson295189b2012-06-20 16:38:30 -07005163 * (NONE/WEP40/WEP104/TKIP/CCMP).
5164 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305165static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
5166 u32 cipher,
Jeff Johnson295189b2012-06-20 16:38:30 -07005167 bool ucast
5168 )
5169{
5170 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305171 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005172 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5173
5174 ENTER();
5175
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305176 if (!cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07005177 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305178 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
Jeff Johnson295189b2012-06-20 16:38:30 -07005179 __func__, cipher);
5180 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5181 }
5182 else
5183 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305184
Jeff Johnson295189b2012-06-20 16:38:30 -07005185 /*set encryption method*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305186 switch (cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07005187 {
5188 case IW_AUTH_CIPHER_NONE:
5189 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5190 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305191
Jeff Johnson295189b2012-06-20 16:38:30 -07005192 case WLAN_CIPHER_SUITE_WEP40:
Gopichand Nakkala29149562013-05-10 21:43:41 +05305193 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
Jeff Johnson295189b2012-06-20 16:38:30 -07005194 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305195
Jeff Johnson295189b2012-06-20 16:38:30 -07005196 case WLAN_CIPHER_SUITE_WEP104:
Gopichand Nakkala29149562013-05-10 21:43:41 +05305197 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
Jeff Johnson295189b2012-06-20 16:38:30 -07005198 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305199
Jeff Johnson295189b2012-06-20 16:38:30 -07005200 case WLAN_CIPHER_SUITE_TKIP:
5201 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5202 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305203
Jeff Johnson295189b2012-06-20 16:38:30 -07005204 case WLAN_CIPHER_SUITE_CCMP:
5205 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5206 break;
5207#ifdef FEATURE_WLAN_WAPI
5208 case WLAN_CIPHER_SUITE_SMS4:
5209 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
5210 break;
5211#endif
5212
5213#ifdef FEATURE_WLAN_CCX
5214 case WLAN_CIPHER_SUITE_KRK:
5215 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
5216 break;
5217#endif
5218 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305219 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005220 __func__, cipher);
5221 return -EOPNOTSUPP;
5222 }
5223 }
5224
5225 if (ucast)
5226 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305227 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005228 __func__, encryptionType);
5229 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5230 pWextState->roamProfile.EncryptionType.numEntries = 1;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305231 pWextState->roamProfile.EncryptionType.encryptionType[0] =
Jeff Johnson295189b2012-06-20 16:38:30 -07005232 encryptionType;
5233 }
5234 else
5235 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305236 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005237 __func__, encryptionType);
5238 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
5239 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
5240 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
5241 }
5242
5243 return 0;
5244}
5245
5246
5247/*
5248 * FUNCTION: wlan_hdd_cfg80211_set_ie
5249 * This function is used to parse WPA/RSN IE's.
5250 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305251int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
5252 u8 *ie,
Jeff Johnson295189b2012-06-20 16:38:30 -07005253 size_t ie_len
5254 )
5255{
5256 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5257 u8 *genie = ie;
5258 v_U16_t remLen = ie_len;
5259#ifdef FEATURE_WLAN_WAPI
5260 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
5261 u16 *tmp;
5262 v_U16_t akmsuiteCount;
5263 int *akmlist;
5264#endif
5265 ENTER();
5266
5267 /* clear previous assocAddIE */
5268 pWextState->assocAddIE.length = 0;
5269 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
5270
5271 while (remLen >= 2)
5272 {
5273 v_U16_t eLen = 0;
5274 v_U8_t elementId;
5275 elementId = *genie++;
5276 eLen = *genie++;
5277 remLen -= 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305278
5279 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07005280 __func__, elementId, eLen);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305281
5282 switch ( elementId )
Jeff Johnson295189b2012-06-20 16:38:30 -07005283 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305284 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005285 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 -07005286 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305287 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005288 "%s: Invalid WPA IE", __func__);
5289 return -EINVAL;
5290 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305291 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
Jeff Johnson295189b2012-06-20 16:38:30 -07005292 {
5293 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305294 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
Jeff Johnson295189b2012-06-20 16:38:30 -07005295 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305296
Jeff Johnson295189b2012-06-20 16:38:30 -07005297 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5298 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005299 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
5300 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005301 VOS_ASSERT(0);
5302 return -ENOMEM;
5303 }
5304 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5305 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5306 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305307
Jeff Johnson295189b2012-06-20 16:38:30 -07005308 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
5309 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5310 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5311 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305312 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
5313 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005314 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
5315 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5316 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
5317 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
5318 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
5319 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305320 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
5321 P2P_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07005322 /*Consider P2P IE, only for P2P Client */
5323 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5324 {
5325 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305326 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
Jeff Johnson295189b2012-06-20 16:38:30 -07005327 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305328
Jeff Johnson295189b2012-06-20 16:38:30 -07005329 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5330 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005331 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5332 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005333 VOS_ASSERT(0);
5334 return -ENOMEM;
5335 }
5336 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5337 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5338 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305339
Jeff Johnson295189b2012-06-20 16:38:30 -07005340 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5341 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5342 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005343#ifdef WLAN_FEATURE_WFD
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305344 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
5345 WFD_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07005346 /*Consider WFD IE, only for P2P Client */
5347 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5348 {
5349 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305350 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD 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 // WFD IE is saved to Additional IE ; it should be accumulated to handle
5361 // WPS IE + P2P IE + WFD IE
5362 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5363 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305364
Jeff Johnson295189b2012-06-20 16:38:30 -07005365 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5366 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5367 }
5368#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005369 /* Appending HS 2.0 Indication Element in Assiciation Request */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305370 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005371 HS20_OUI_TYPE_SIZE)) )
5372 {
5373 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305374 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005375 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005376
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005377 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5378 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005379 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5380 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005381 VOS_ASSERT(0);
5382 return -ENOMEM;
5383 }
5384 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5385 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005386
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005387 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5388 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5389 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005390
Jeff Johnson295189b2012-06-20 16:38:30 -07005391 break;
5392 case DOT11F_EID_RSN:
5393 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
5394 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5395 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
5396 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
5397 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
5398 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005399 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
5400 case DOT11F_EID_EXTCAP:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305401 {
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005402 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305403 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005404 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305405
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005406 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5407 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005408 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5409 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005410 VOS_ASSERT(0);
5411 return -ENOMEM;
5412 }
5413 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5414 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305415
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005416 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5417 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5418 break;
5419 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005420#ifdef FEATURE_WLAN_WAPI
5421 case WLAN_EID_WAPI:
5422 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
5423 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
5424 pAdapter->wapi_info.nWapiMode);
5425 tmp = (u16 *)ie;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305426 tmp = tmp + 2; // Skip element Id and Len, Version
Jeff Johnson295189b2012-06-20 16:38:30 -07005427 akmsuiteCount = WPA_GET_LE16(tmp);
5428 tmp = tmp + 1;
5429 akmlist = (int *)(tmp);
5430 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
5431 {
5432 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
5433 }
5434 else
5435 {
5436 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
5437 VOS_ASSERT(0);
5438 return -EINVAL;
5439 }
5440
5441 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
5442 {
5443 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005444 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005445 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305446 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005447 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305448 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005449 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005450 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005451 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
5452 }
5453 break;
5454#endif
5455 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305456 hddLog (VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005457 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005458 /* when Unknown IE is received we should break and continue
5459 * to the next IE in the buffer instead we were returning
5460 * so changing this to break */
5461 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005462 }
5463 genie += eLen;
5464 remLen -= eLen;
5465 }
5466 EXIT();
5467 return 0;
5468}
5469
5470/*
Gopichand Nakkala18f0c262013-05-07 23:25:08 +05305471 * FUNCTION: hdd_isWPAIEPresent
5472 * Parse the received IE to find the WPA IE
5473 *
5474 */
5475static bool hdd_isWPAIEPresent(u8 *ie, u8 ie_len)
5476{
5477 v_U8_t eLen = 0;
5478 v_U16_t remLen = ie_len;
5479 v_U8_t elementId = 0;
5480
5481 while (remLen >= 2)
5482 {
5483 elementId = *ie++;
5484 eLen = *ie++;
5485 remLen -= 2;
5486 if (eLen > remLen)
5487 {
5488 hddLog(VOS_TRACE_LEVEL_ERROR,
5489 "%s: IE length is wrong %d", __func__, eLen);
5490 return FALSE;
5491 }
5492 if ((elementId == DOT11F_EID_WPA) && (remLen > 5))
5493 {
5494 /* OUI - 0x00 0X50 0XF2
5495 WPA Information Element - 0x01
5496 WPA version - 0x01*/
5497 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
5498 return TRUE;
5499 }
5500 ie += eLen;
5501 remLen -= eLen;
5502 }
5503 return FALSE;
5504}
5505
5506/*
Jeff Johnson295189b2012-06-20 16:38:30 -07005507 * FUNCTION: wlan_hdd_cfg80211_set_privacy
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305508 * This function is used to initialize the security
Jeff Johnson295189b2012-06-20 16:38:30 -07005509 * parameters during connect operation.
5510 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305511int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07005512 struct cfg80211_connect_params *req
5513 )
5514{
5515 int status = 0;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305516 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005517 ENTER();
5518
5519 /*set wpa version*/
5520 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5521
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305522 if (req->crypto.wpa_versions)
Jeff Johnson295189b2012-06-20 16:38:30 -07005523 {
Gopichand Nakkala781ded42013-06-28 12:10:45 +05305524 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
Jeff Johnson295189b2012-06-20 16:38:30 -07005525 {
5526 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5527 }
5528 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
5529 {
5530 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5531 }
5532 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305533
5534 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07005535 pWextState->wpaVersion);
5536
5537 /*set authentication type*/
5538 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
5539
5540 if (0 > status)
5541 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305542 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005543 "%s: failed to set authentication type ", __func__);
5544 return status;
5545 }
5546
5547 /*set key mgmt type*/
5548 if (req->crypto.n_akm_suites)
5549 {
5550 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
5551 if (0 > status)
5552 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305553 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
Jeff Johnson295189b2012-06-20 16:38:30 -07005554 __func__);
5555 return status;
5556 }
5557 }
5558
5559 /*set pairwise cipher type*/
5560 if (req->crypto.n_ciphers_pairwise)
5561 {
5562 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
5563 req->crypto.ciphers_pairwise[0], true);
5564 if (0 > status)
5565 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305566 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005567 "%s: failed to set unicast cipher type", __func__);
5568 return status;
5569 }
5570 }
5571 else
5572 {
5573 /*Reset previous cipher suite to none*/
5574 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
5575 if (0 > status)
5576 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305577 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005578 "%s: failed to set unicast cipher type", __func__);
5579 return status;
5580 }
5581 }
5582
5583 /*set group cipher type*/
5584 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
5585 false);
5586
5587 if (0 > status)
5588 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305589 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
Jeff Johnson295189b2012-06-20 16:38:30 -07005590 __func__);
5591 return status;
5592 }
5593
Chet Lanctot186b5732013-03-18 10:26:30 -07005594#ifdef WLAN_FEATURE_11W
5595 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
5596#endif
5597
Jeff Johnson295189b2012-06-20 16:38:30 -07005598 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
5599 if (req->ie_len)
5600 {
5601 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
5602 if ( 0 > status)
5603 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305604 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
Jeff Johnson295189b2012-06-20 16:38:30 -07005605 __func__);
5606 return status;
5607 }
5608 }
5609
5610 /*incase of WEP set default key information*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305611 if (req->key && req->key_len)
Jeff Johnson295189b2012-06-20 16:38:30 -07005612 {
5613 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
5614 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
5615 )
5616 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305617 if ( IW_AUTH_KEY_MGMT_802_1X
Jeff Johnson295189b2012-06-20 16:38:30 -07005618 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
5619 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305620 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
Jeff Johnson295189b2012-06-20 16:38:30 -07005621 __func__);
5622 return -EOPNOTSUPP;
5623 }
5624 else
5625 {
5626 u8 key_len = req->key_len;
5627 u8 key_idx = req->key_idx;
5628
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305629 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
Jeff Johnson295189b2012-06-20 16:38:30 -07005630 && (CSR_MAX_NUM_KEY > key_idx)
5631 )
5632 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305633 hddLog(VOS_TRACE_LEVEL_INFO,
5634 "%s: setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07005635 __func__, key_idx, key_len);
5636 vos_mem_copy(
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305637 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07005638 req->key, key_len);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305639 pWextState->roamProfile.Keys.KeyLength[key_idx] =
Jeff Johnson295189b2012-06-20 16:38:30 -07005640 (u8)key_len;
5641 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
5642 }
5643 }
5644 }
5645 }
5646
5647 return status;
5648}
5649
5650/*
5651 * FUNCTION: wlan_hdd_cfg80211_set_privacy
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305652 * This function is used to initialize the security
Jeff Johnson295189b2012-06-20 16:38:30 -07005653 * parameters during connect operation.
5654 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305655static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07005656 struct net_device *ndev,
5657 struct cfg80211_connect_params *req
5658 )
5659{
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305660 int status;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305661 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07005662 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
5663 hdd_context_t *pHddCtx = NULL;
5664
5665 ENTER();
5666
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305667 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07005668 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5669
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305670 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5671 status = wlan_hdd_validate_context(pHddCtx);
5672
5673 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07005674 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305675 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5676 "%s: HDD context is not valid", __func__);
5677 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07005678 }
5679
5680#ifdef WLAN_BTAMP_FEATURE
5681 //Infra connect not supported when AMP traffic is on.
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305682 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
Jeff Johnson295189b2012-06-20 16:38:30 -07005683 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305684 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005685 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005686 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07005687 }
5688#endif
5689 /*initialise security parameters*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305690 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
Jeff Johnson295189b2012-06-20 16:38:30 -07005691
5692 if ( 0 > status)
5693 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305694 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
Jeff Johnson295189b2012-06-20 16:38:30 -07005695 __func__);
5696 return status;
5697 }
5698
5699 //If Device Mode is Station Concurrent Sessions Exit BMps
Jeff Johnsona8a1a482012-12-12 16:49:33 -08005700 //P2P Mode will be taken care in Open/close adapter
Jeff Johnson295189b2012-06-20 16:38:30 -07005701 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
5702 (vos_concurrent_sessions_running()))
5703 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305704 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
Jeff Johnson295189b2012-06-20 16:38:30 -07005705 }
5706
Mohit Khanna765234a2012-09-11 15:08:35 -07005707 if ( req->channel )
5708 {
5709 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5710 req->ssid_len, req->bssid,
5711 req->channel->hw_value);
5712 }
5713 else
5714 {
5715 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305716 req->ssid_len, req->bssid, 0);
Mohit Khanna765234a2012-09-11 15:08:35 -07005717 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005718
5719 if (0 > status)
5720 {
5721 //ReEnable BMPS if disabled
5722 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5723 (NULL != pHddCtx))
5724 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305725 if (pHddCtx->hdd_wlan_suspended)
5726 {
5727 hdd_set_pwrparams(pHddCtx);
5728 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005729 //ReEnable Bmps and Imps back
5730 hdd_enable_bmps_imps(pHddCtx);
5731 }
5732
5733 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5734 return status;
5735 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305736 pHddCtx->isAmpAllowed = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005737 EXIT();
5738 return status;
5739}
5740
5741
5742/*
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05305743 * FUNCTION: wlan_hdd_disconnect
5744 * This function is used to issue a disconnect request to SME
5745 */
5746int wlan_hdd_disconnect( hdd_adapter_t *pAdapter, u16 reason )
5747{
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305748 int status;
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05305749 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305750 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5751
5752 status = wlan_hdd_validate_context(pHddCtx);
5753
5754 if (0 != status)
5755 {
5756 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5757 "%s: HDD context is not valid", __func__);
5758 return status;
5759 }
5760
5761 pHddCtx->isAmpAllowed = VOS_TRUE;
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05305762 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05305763 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305764
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05305765 /*issue disconnect*/
5766 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5767 pAdapter->sessionId, reason);
5768
5769 if ( 0 != status )
5770 {
5771 hddLog(VOS_TRACE_LEVEL_ERROR,
5772 "%s csrRoamDisconnect failure, returned %d \n",
5773 __func__, (int)status );
5774 return -EINVAL;
5775 }
5776 wait_for_completion_interruptible_timeout(
5777 &pAdapter->disconnect_comp_var,
5778 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5779 /*stop tx queues*/
5780 netif_tx_disable(pAdapter->dev);
5781 netif_carrier_off(pAdapter->dev);
5782 return status;
5783}
5784
5785
5786/*
Jeff Johnson295189b2012-06-20 16:38:30 -07005787 * FUNCTION: wlan_hdd_cfg80211_disconnect
5788 * This function is used to issue a disconnect request to SME
5789 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305790static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07005791 struct net_device *dev,
5792 u16 reason
5793 )
5794{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305795 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5796 tCsrRoamProfile *pRoamProfile =
Jeff Johnson295189b2012-06-20 16:38:30 -07005797 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305798 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07005799 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005800 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05305801#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005802 tANI_U8 staIdx;
5803#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305804
Jeff Johnson295189b2012-06-20 16:38:30 -07005805 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305806
5807 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07005808 __func__,pAdapter->device_mode);
5809
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305810 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5811 __func__, reason);
Jeff Johnson295189b2012-06-20 16:38:30 -07005812
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305813 status = wlan_hdd_validate_context(pHddCtx);
5814
5815 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07005816 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305817 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5818 "%s: HDD context is not valid", __func__);
5819 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07005820 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305821
Jeff Johnson295189b2012-06-20 16:38:30 -07005822 if (NULL != pRoamProfile)
5823 {
5824 /*issue disconnect request to SME, if station is in connected state*/
5825 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
5826 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305827 eCsrRoamDisconnectReason reasonCode =
Jeff Johnson295189b2012-06-20 16:38:30 -07005828 eCSR_DISCONNECT_REASON_UNSPECIFIED;
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05305829 hdd_scaninfo_t *pScanInfo;
Jeff Johnson295189b2012-06-20 16:38:30 -07005830 switch(reason)
5831 {
5832 case WLAN_REASON_MIC_FAILURE:
5833 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
5834 break;
5835
5836 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
5837 case WLAN_REASON_DISASSOC_AP_BUSY:
5838 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
5839 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
5840 break;
5841
5842 case WLAN_REASON_PREV_AUTH_NOT_VALID:
5843 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
5844 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
5845 break;
5846
5847 case WLAN_REASON_DEAUTH_LEAVING:
5848 default:
5849 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
5850 break;
5851 }
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05305852 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5853 pScanInfo = &pHddCtx->scan_info;
5854 if (pScanInfo->mScanPending)
5855 {
5856 hddLog(VOS_TRACE_LEVEL_INFO, "Disconnect is in progress, "
5857 "Aborting Scan");
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05305858 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05305859 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005860
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005861#ifdef FEATURE_WLAN_TDLS
5862 /* First clean up the tdls peers if any */
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005863 for (staIdx = 0 ; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005864 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005865 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId == pAdapter->sessionId) &&
5866 (pHddCtx->tdlsConnInfo[staIdx].staId))
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005867 {
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005868 uint8 *mac;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005869 mac = pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005870 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07005871 "%s: call sme_DeleteTdlsPeerSta staId %d sessionId %d " MAC_ADDRESS_STR,
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005872 __func__, pHddCtx->tdlsConnInfo[staIdx].staId, pAdapter->sessionId,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07005873 MAC_ADDR_ARRAY(mac));
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005874 sme_DeleteTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005875 pAdapter->sessionId,
5876 mac);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005877 }
5878 }
5879#endif
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05305880 status = wlan_hdd_disconnect(pAdapter, reasonCode);
5881 if ( 0 != status )
Jeff Johnson295189b2012-06-20 16:38:30 -07005882 {
5883 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05305884 "%s wlan_hdd_disconnect failure, returned %d \n",
Jeff Johnson295189b2012-06-20 16:38:30 -07005885 __func__, (int)status );
5886 return -EINVAL;
5887 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005888 }
5889 }
5890 else
5891 {
5892 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
5893 }
5894
5895 return status;
5896}
5897
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05305898
Jeff Johnson295189b2012-06-20 16:38:30 -07005899/*
5900 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305901 * This function is used to initialize the security
Jeff Johnson295189b2012-06-20 16:38:30 -07005902 * settings in IBSS mode.
5903 */
5904static int wlan_hdd_cfg80211_set_privacy_ibss(
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305905 hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07005906 struct cfg80211_ibss_params *params
5907 )
5908{
5909 int status = 0;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305910 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005911 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5912 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305913
Jeff Johnson295189b2012-06-20 16:38:30 -07005914 ENTER();
5915
5916 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5917
5918 if (params->ie_len && ( NULL != params->ie) )
5919 {
Shailender Karmuchi67edd312013-06-18 16:30:48 -07005920 if (wlan_hdd_cfg80211_get_ie_ptr (params->ie,
5921 params->ie_len, WLAN_EID_RSN ))
Jeff Johnson295189b2012-06-20 16:38:30 -07005922 {
5923 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5924 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5925 }
Shailender Karmuchi67edd312013-06-18 16:30:48 -07005926 else if ( hdd_isWPAIEPresent (params->ie, params->ie_len ))
Jeff Johnson295189b2012-06-20 16:38:30 -07005927 {
Shailender Karmuchi642e9812013-05-30 14:34:49 -07005928 tDot11fIEWPA dot11WPAIE;
5929 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
Shailender Karmuchi67edd312013-06-18 16:30:48 -07005930 u8 *ie;
Shailender Karmuchi642e9812013-05-30 14:34:49 -07005931
Shailender Karmuchi67edd312013-06-18 16:30:48 -07005932 ie = wlan_hdd_cfg80211_get_ie_ptr (params->ie,
5933 params->ie_len, DOT11F_EID_WPA);
5934 if ( NULL != ie )
5935 {
5936 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5937 // Unpack the WPA IE
5938 //Skip past the EID byte and length byte - and four byte WiFi OUI
5939 dot11fUnpackIeWPA((tpAniSirGlobal) halHandle,
5940 &ie[2+4],
5941 ie[1] - 4,
5942 &dot11WPAIE);
5943 /*Extract the multicast cipher, the encType for unicast
5944 cipher for wpa-none is none*/
5945 encryptionType =
5946 hdd_TranslateWPAToCsrEncryptionType(dot11WPAIE.multicast_cipher);
5947 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005948 }
Shailender Karmuchi67edd312013-06-18 16:30:48 -07005949
Jeff Johnson295189b2012-06-20 16:38:30 -07005950 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
5951
5952 if (0 > status)
5953 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305954 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
Jeff Johnson295189b2012-06-20 16:38:30 -07005955 __func__);
5956 return status;
5957 }
5958 }
5959
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305960 pWextState->roamProfile.AuthType.authType[0] =
5961 pHddStaCtx->conn_info.authType =
Jeff Johnson295189b2012-06-20 16:38:30 -07005962 eCSR_AUTH_TYPE_OPEN_SYSTEM;
5963
5964 if (params->privacy)
5965 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305966 /* Security enabled IBSS, At this time there is no information available
5967 * about the security paramters, so initialise the encryption type to
Jeff Johnson295189b2012-06-20 16:38:30 -07005968 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305969 * The correct security parameters will be updated later in
Jeff Johnson295189b2012-06-20 16:38:30 -07005970 * wlan_hdd_cfg80211_add_key */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305971 /* Hal expects encryption type to be set inorder
Jeff Johnson295189b2012-06-20 16:38:30 -07005972 *enable privacy bit in beacons */
5973
5974 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5975 }
Shailender Karmuchi642e9812013-05-30 14:34:49 -07005976 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
5977 "encryptionType=%d", encryptionType);
Jeff Johnson295189b2012-06-20 16:38:30 -07005978 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5979 pWextState->roamProfile.EncryptionType.numEntries = 1;
5980 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
Jeff Johnson295189b2012-06-20 16:38:30 -07005981 return status;
5982}
5983
5984/*
5985 * FUNCTION: wlan_hdd_cfg80211_join_ibss
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305986 * This function is used to create/join an IBSS
Jeff Johnson295189b2012-06-20 16:38:30 -07005987 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305988static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07005989 struct net_device *dev,
5990 struct cfg80211_ibss_params *params
5991 )
5992{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305993 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07005994 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5995 tCsrRoamProfile *pRoamProfile;
5996 int status;
5997 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305998 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005999
6000 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306001
6002 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07006003 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
6004
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306005 status = wlan_hdd_validate_context(pHddCtx);
6006
6007 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07006008 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306009 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6010 "%s: HDD context is not valid", __func__);
6011 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006012 }
6013
6014 if (NULL == pWextState)
6015 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306016 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07006017 __func__);
6018 return -EIO;
6019 }
6020
6021 pRoamProfile = &pWextState->roamProfile;
6022
6023 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
6024 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306025 hddLog (VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006026 "%s Interface type is not set to IBSS \n", __func__);
6027 return -EINVAL;
6028 }
6029
6030 /* Set Channel */
Yue Maf49ba872013-08-19 12:04:25 -07006031 if (NULL !=
6032#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
6033 params->chandef.chan)
6034#else
6035 params->channel)
6036#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006037 {
6038 u8 channelNum;
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006039 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6040 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
6041 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
6042 int indx;
Jeff Johnson295189b2012-06-20 16:38:30 -07006043
6044 /* Get channel number */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306045 channelNum =
Yue Maf49ba872013-08-19 12:04:25 -07006046 ieee80211_frequency_to_channel(
6047#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
6048 params->chandef.chan->center_freq);
6049#else
6050 params->channel->center_freq);
6051#endif
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006052
6053 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
6054 validChan, &numChans))
Jeff Johnson295189b2012-06-20 16:38:30 -07006055 {
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006056 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
6057 __func__);
6058 return -EOPNOTSUPP;
Jeff Johnson295189b2012-06-20 16:38:30 -07006059 }
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006060
6061 for (indx = 0; indx < numChans; indx++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006062 {
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006063 if (channelNum == validChan[indx])
6064 {
6065 break;
6066 }
6067 }
6068 if (indx >= numChans)
6069 {
6070 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07006071 __func__, channelNum);
6072 return -EINVAL;
6073 }
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006074 /* Set the Operational Channel */
6075 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
6076 channelNum);
6077 pRoamProfile->ChannelInfo.numOfChannels = 1;
6078 pHddStaCtx->conn_info.operationChannel = channelNum;
6079 pRoamProfile->ChannelInfo.ChannelList =
6080 &pHddStaCtx->conn_info.operationChannel;
Jeff Johnson295189b2012-06-20 16:38:30 -07006081 }
6082
6083 /* Initialize security parameters */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306084 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
Jeff Johnson295189b2012-06-20 16:38:30 -07006085 if (status < 0)
6086 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306087 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
Jeff Johnson295189b2012-06-20 16:38:30 -07006088 __func__);
6089 return status;
6090 }
6091
6092 /* Issue connect start */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306093 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006094 params->ssid_len, params->bssid,
6095 pHddStaCtx->conn_info.operationChannel);
Jeff Johnson295189b2012-06-20 16:38:30 -07006096
6097 if (0 > status)
6098 {
6099 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
6100 return status;
6101 }
6102
6103 return 0;
6104}
6105
6106/*
6107 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306108 * This function is used to leave an IBSS
Jeff Johnson295189b2012-06-20 16:38:30 -07006109 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306110static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006111 struct net_device *dev
6112 )
6113{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306114 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07006115 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6116 tCsrRoamProfile *pRoamProfile;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306117 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6118 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006119
6120 ENTER();
6121
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306122 status = wlan_hdd_validate_context(pHddCtx);
6123
6124 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006125 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306126 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6127 "%s: HDD context is not valid", __func__);
6128 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006129 }
6130
Jeff Johnson295189b2012-06-20 16:38:30 -07006131 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
6132 if (NULL == pWextState)
6133 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306134 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07006135 __func__);
6136 return -EIO;
6137 }
6138
6139 pRoamProfile = &pWextState->roamProfile;
6140
6141 /* Issue disconnect only if interface type is set to IBSS */
6142 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
6143 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306144 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
Jeff Johnson295189b2012-06-20 16:38:30 -07006145 __func__);
6146 return -EINVAL;
6147 }
6148
6149 /* Issue Disconnect request */
6150 INIT_COMPLETION(pAdapter->disconnect_comp_var);
6151 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6152 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6153
6154 return 0;
6155}
6156
6157/*
6158 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
6159 * This function is used to set the phy parameters
6160 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
6161 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306162static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006163 u32 changed)
6164{
6165 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6166 tHalHandle hHal = pHddCtx->hHal;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306167 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006168
6169 ENTER();
6170
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306171 status = wlan_hdd_validate_context(pHddCtx);
6172
6173 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006174 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306175 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6176 "%s: HDD context is not valid", __func__);
6177 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006178 }
6179
Jeff Johnson295189b2012-06-20 16:38:30 -07006180 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
6181 {
6182 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
6183 WNI_CFG_RTS_THRESHOLD_STAMAX :
6184 wiphy->rts_threshold;
6185
6186 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306187 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
Jeff Johnson295189b2012-06-20 16:38:30 -07006188 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306189 hddLog(VOS_TRACE_LEVEL_ERROR,
6190 "%s: Invalid RTS Threshold value %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006191 __func__, rts_threshold);
6192 return -EINVAL;
6193 }
6194
6195 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
6196 rts_threshold, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306197 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07006198 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306199 hddLog(VOS_TRACE_LEVEL_ERROR,
6200 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006201 __func__, rts_threshold);
6202 return -EIO;
6203 }
6204
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306205 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07006206 rts_threshold);
6207 }
6208
6209 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
6210 {
6211 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
6212 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
6213 wiphy->frag_threshold;
6214
6215 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306216 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
Jeff Johnson295189b2012-06-20 16:38:30 -07006217 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306218 hddLog(VOS_TRACE_LEVEL_ERROR,
6219 "%s: Invalid frag_threshold value %hu", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07006220 frag_threshold);
6221 return -EINVAL;
6222 }
6223
6224 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
6225 frag_threshold, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306226 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07006227 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306228 hddLog(VOS_TRACE_LEVEL_ERROR,
6229 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006230 __func__, frag_threshold);
6231 return -EIO;
6232 }
6233
6234 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
6235 frag_threshold);
6236 }
6237
6238 if ((changed & WIPHY_PARAM_RETRY_SHORT)
6239 || (changed & WIPHY_PARAM_RETRY_LONG))
6240 {
6241 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
6242 wiphy->retry_short :
6243 wiphy->retry_long;
6244
6245 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
6246 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
6247 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306248 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006249 __func__, retry_value);
6250 return -EINVAL;
6251 }
6252
6253 if (changed & WIPHY_PARAM_RETRY_SHORT)
6254 {
6255 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
6256 retry_value, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306257 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07006258 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306259 hddLog(VOS_TRACE_LEVEL_ERROR,
6260 "%s: ccmCfgSetInt failed for long retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006261 __func__, retry_value);
6262 return -EIO;
6263 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306264 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006265 __func__, retry_value);
6266 }
6267 else if (changed & WIPHY_PARAM_RETRY_SHORT)
6268 {
6269 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
6270 retry_value, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306271 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07006272 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306273 hddLog(VOS_TRACE_LEVEL_ERROR,
6274 "%s: ccmCfgSetInt failed for short retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006275 __func__, retry_value);
6276 return -EIO;
6277 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306278 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006279 __func__, retry_value);
6280 }
6281 }
6282
6283 return 0;
6284}
6285
6286/*
6287 * FUNCTION: wlan_hdd_cfg80211_set_txpower
6288 * This function is used to set the txpower
6289 */
6290static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
Yue Maf49ba872013-08-19 12:04:25 -07006291#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
6292 struct wireless_dev *wdev,
6293#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006294#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306295 enum tx_power_setting type,
Jeff Johnson295189b2012-06-20 16:38:30 -07006296#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306297 enum nl80211_tx_power_setting type,
Jeff Johnson295189b2012-06-20 16:38:30 -07006298#endif
6299 int dbm)
6300{
6301 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306302 tHalHandle hHal = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006303 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
6304 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306305 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006306
6307 ENTER();
6308
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306309 status = wlan_hdd_validate_context(pHddCtx);
6310
6311 if (0 != status)
6312 {
6313 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6314 "%s: HDD context is not valid", __func__);
6315 return status;
6316 }
6317
6318 hHal = pHddCtx->hHal;
6319
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306320 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
6321 dbm, ccmCfgSetCallback,
6322 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07006323 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306324 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006325 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
6326 return -EIO;
6327 }
6328
6329 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
6330 dbm);
6331
6332 switch(type)
6333 {
6334 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
6335 /* Fall through */
6336 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
6337 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
6338 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306339 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
6340 __func__);
6341 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006342 }
6343 break;
6344 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306345 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
Jeff Johnson295189b2012-06-20 16:38:30 -07006346 __func__);
6347 return -EOPNOTSUPP;
6348 break;
6349 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306350 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
6351 __func__, type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006352 return -EIO;
6353 }
6354
6355 return 0;
6356}
6357
6358/*
6359 * FUNCTION: wlan_hdd_cfg80211_get_txpower
6360 * This function is used to read the txpower
6361 */
Yue Maf49ba872013-08-19 12:04:25 -07006362static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy,
6363#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
6364 struct wireless_dev *wdev,
6365#endif
6366 int *dbm)
Jeff Johnson295189b2012-06-20 16:38:30 -07006367{
6368
6369 hdd_adapter_t *pAdapter;
6370 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306371 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006372
Jeff Johnsone7245742012-09-05 17:12:55 -07006373 ENTER();
6374
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306375 status = wlan_hdd_validate_context(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006376
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306377 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006378 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306379 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6380 "%s: HDD context is not valid", __func__);
6381 *dbm = 0;
6382 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006383 }
6384
Jeff Johnson295189b2012-06-20 16:38:30 -07006385 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
6386 if (NULL == pAdapter)
6387 {
6388 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
6389 return -ENOENT;
6390 }
6391
6392 wlan_hdd_get_classAstats(pAdapter);
6393 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
6394
Jeff Johnsone7245742012-09-05 17:12:55 -07006395 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006396 return 0;
6397}
6398
6399static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
6400 u8* mac, struct station_info *sinfo)
6401{
6402 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
6403 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6404 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
6405 tANI_U8 rate_flags;
6406
6407 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6408 hdd_config_t *pCfg = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07006409
6410 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
6411 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
6412 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
6413 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
6414 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
6415 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
6416 tANI_U16 maxRate = 0;
6417 tANI_U16 myRate;
6418 tANI_U16 currentRate = 0;
6419 tANI_U8 maxSpeedMCS = 0;
6420 tANI_U8 maxMCSIdx = 0;
6421 tANI_U8 rateFlag = 1;
6422 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006423 tANI_U16 temp;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306424 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006425
Leo Chang6f8870f2013-03-26 18:11:36 -07006426#ifdef WLAN_FEATURE_11AC
6427 tANI_U32 vht_mcs_map;
6428 eDataRate11ACMaxMcs vhtMaxMcs;
6429#endif /* WLAN_FEATURE_11AC */
6430
Jeff Johnsone7245742012-09-05 17:12:55 -07006431 ENTER();
6432
Jeff Johnson295189b2012-06-20 16:38:30 -07006433 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
6434 (0 == ssidlen))
6435 {
6436 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
6437 " Invalid ssidlen, %d", __func__, ssidlen);
6438 /*To keep GUI happy*/
6439 return 0;
6440 }
6441
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306442 status = wlan_hdd_validate_context(pHddCtx);
6443
6444 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006445 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306446 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6447 "%s: HDD context is not valid", __func__);
6448 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006449 }
6450
Jeff Johnson295189b2012-06-20 16:38:30 -07006451 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
6452 sinfo->filled |= STATION_INFO_SIGNAL;
6453
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006454 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006455 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
6456
6457 //convert to the UI units of 100kbps
6458 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
6459
6460#ifdef LINKSPEED_DEBUG_ENABLED
Leo Chang6f8870f2013-03-26 18:11:36 -07006461 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 -07006462 sinfo->signal,
6463 pCfg->reportMaxLinkSpeed,
6464 myRate,
6465 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006466 (int) pCfg->linkSpeedRssiMid,
6467 (int) pCfg->linkSpeedRssiLow,
Leo Chang6f8870f2013-03-26 18:11:36 -07006468 (int) rate_flags,
6469 (int) pAdapter->hdd_stats.ClassA_stat.mcs_index);
Jeff Johnson295189b2012-06-20 16:38:30 -07006470#endif //LINKSPEED_DEBUG_ENABLED
6471
6472 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
6473 {
6474 // we do not want to necessarily report the current speed
6475 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
6476 {
6477 // report the max possible speed
6478 rssidx = 0;
6479 }
6480 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
6481 {
6482 // report the max possible speed with RSSI scaling
6483 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
6484 {
6485 // report the max possible speed
6486 rssidx = 0;
6487 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006488 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07006489 {
6490 // report middle speed
6491 rssidx = 1;
6492 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006493 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
6494 {
6495 // report middle speed
6496 rssidx = 2;
6497 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006498 else
6499 {
6500 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006501 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07006502 }
6503 }
6504 else
6505 {
6506 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
6507 hddLog(VOS_TRACE_LEVEL_ERROR,
6508 "%s: Invalid value for reportMaxLinkSpeed: %u",
6509 __func__, pCfg->reportMaxLinkSpeed);
6510 rssidx = 0;
6511 }
6512
6513 maxRate = 0;
6514
6515 /* Get Basic Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306516 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_OPERATIONAL_RATE_SET,
6517 OperationalRates, &ORLeng))
6518 {
6519 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6520 /*To keep GUI happy*/
6521 return 0;
6522 }
6523
Jeff Johnson295189b2012-06-20 16:38:30 -07006524 for (i = 0; i < ORLeng; i++)
6525 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006526 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006527 {
6528 /* Validate Rate Set */
6529 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
6530 {
6531 currentRate = supported_data_rate[j].supported_rate[rssidx];
6532 break;
6533 }
6534 }
6535 /* Update MAX rate */
6536 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6537 }
6538
6539 /* Get Extended Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306540 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
6541 ExtendedRates, &ERLeng))
6542 {
6543 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6544 /*To keep GUI happy*/
6545 return 0;
6546 }
6547
Jeff Johnson295189b2012-06-20 16:38:30 -07006548 for (i = 0; i < ERLeng; i++)
6549 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006550 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006551 {
6552 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
6553 {
6554 currentRate = supported_data_rate[j].supported_rate[rssidx];
6555 break;
6556 }
6557 }
6558 /* Update MAX rate */
6559 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6560 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006561 /* Get MCS Rate Set -- but only if we are connected at MCS
6562 rates or if we are always reporting max speed or if we have
6563 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006564 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07006565 {
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306566 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_CURRENT_MCS_SET,
6567 MCSRates, &MCSLeng))
6568 {
6569 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6570 /*To keep GUI happy*/
6571 return 0;
6572 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006573 rateFlag = 0;
Leo Chang6f8870f2013-03-26 18:11:36 -07006574#ifdef WLAN_FEATURE_11AC
6575 /* VHT80 rate has seperate rate table */
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306576 if (rate_flags & (eHAL_TX_RATE_VHT20|eHAL_TX_RATE_VHT40|eHAL_TX_RATE_VHT80))
Jeff Johnson295189b2012-06-20 16:38:30 -07006577 {
Leo Chang6f8870f2013-03-26 18:11:36 -07006578 ccmCfgGetInt(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_VHT_TX_MCS_MAP, &vht_mcs_map);
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306579 vhtMaxMcs = (eDataRate11ACMaxMcs)(vht_mcs_map & DATA_RATE_11AC_MCS_MASK );
Leo Chang6f8870f2013-03-26 18:11:36 -07006580 if (rate_flags & eHAL_TX_RATE_SGI)
Jeff Johnson295189b2012-06-20 16:38:30 -07006581 {
Leo Chang6f8870f2013-03-26 18:11:36 -07006582 rateFlag |= 1;
Jeff Johnson295189b2012-06-20 16:38:30 -07006583 }
Leo Chang6f8870f2013-03-26 18:11:36 -07006584 if (DATA_RATE_11AC_MAX_MCS_7 == vhtMaxMcs)
Jeff Johnson295189b2012-06-20 16:38:30 -07006585 {
Leo Chang6f8870f2013-03-26 18:11:36 -07006586 maxMCSIdx = 7;
6587 }
6588 else if (DATA_RATE_11AC_MAX_MCS_8 == vhtMaxMcs)
6589 {
6590 maxMCSIdx = 8;
6591 }
6592 else if (DATA_RATE_11AC_MAX_MCS_9 == vhtMaxMcs)
6593 {
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306594 //VHT20 is supporting 0~8
6595 if (rate_flags & eHAL_TX_RATE_VHT20)
6596 maxMCSIdx = 8;
6597 else
6598 maxMCSIdx = 9;
Leo Chang6f8870f2013-03-26 18:11:36 -07006599 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306600
6601 if (rate_flags & eHAL_TX_RATE_VHT80)
6602 {
6603 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT80_rate[rateFlag];
6604 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT80_rate[rateFlag];
6605 }
6606 else if (rate_flags & eHAL_TX_RATE_VHT40)
6607 {
6608 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT40_rate[rateFlag];
6609 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT40_rate[rateFlag];
6610 }
6611 else if (rate_flags & eHAL_TX_RATE_VHT20)
6612 {
6613 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT20_rate[rateFlag];
6614 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT20_rate[rateFlag];
6615 }
6616
Leo Chang6f8870f2013-03-26 18:11:36 -07006617 maxSpeedMCS = 1;
6618 if (currentRate > maxRate)
6619 {
6620 maxRate = currentRate;
6621 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306622
Leo Chang6f8870f2013-03-26 18:11:36 -07006623 }
6624 else
6625#endif /* WLAN_FEATURE_11AC */
6626 {
6627 if (rate_flags & eHAL_TX_RATE_HT40)
6628 {
6629 rateFlag |= 1;
6630 }
6631 if (rate_flags & eHAL_TX_RATE_SGI)
6632 {
6633 rateFlag |= 2;
6634 }
6635
6636 for (i = 0; i < MCSLeng; i++)
6637 {
6638 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
6639 for (j = 0; j < temp; j++)
6640 {
6641 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
6642 {
6643 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
6644 break;
6645 }
6646 }
6647 if ((j < temp) && (currentRate > maxRate))
6648 {
6649 maxRate = currentRate;
6650 maxSpeedMCS = 1;
6651 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
6652 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006653 }
6654 }
6655 }
6656
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306657 else if (!(rate_flags & eHAL_TX_RATE_LEGACY))
6658 {
6659 maxRate = myRate;
6660 maxSpeedMCS = 1;
6661 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6662 }
6663
Jeff Johnson295189b2012-06-20 16:38:30 -07006664 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006665 if (((maxRate < myRate) && (0 == rssidx)) ||
6666 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006667 {
6668 maxRate = myRate;
6669 if (rate_flags & eHAL_TX_RATE_LEGACY)
6670 {
6671 maxSpeedMCS = 0;
6672 }
6673 else
6674 {
6675 maxSpeedMCS = 1;
6676 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6677 }
6678 }
6679
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306680 if (rate_flags & eHAL_TX_RATE_LEGACY)
Jeff Johnson295189b2012-06-20 16:38:30 -07006681 {
6682 sinfo->txrate.legacy = maxRate;
6683#ifdef LINKSPEED_DEBUG_ENABLED
6684 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
6685#endif //LINKSPEED_DEBUG_ENABLED
6686 }
6687 else
6688 {
6689 sinfo->txrate.mcs = maxMCSIdx;
Leo Chang6f8870f2013-03-26 18:11:36 -07006690#ifdef WLAN_FEATURE_11AC
6691 sinfo->txrate.nss = 1;
6692 if (rate_flags & eHAL_TX_RATE_VHT80)
6693 {
6694 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306695 sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Leo Chang6f8870f2013-03-26 18:11:36 -07006696 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306697 else if (rate_flags & eHAL_TX_RATE_VHT40)
Leo Chang6f8870f2013-03-26 18:11:36 -07006698 {
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306699 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
6700 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6701 }
6702 else if (rate_flags & eHAL_TX_RATE_VHT20)
6703 {
6704 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
6705 }
6706#endif /* WLAN_FEATURE_11AC */
6707 if (rate_flags & (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40))
6708 {
6709 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6710 if (rate_flags & eHAL_TX_RATE_HT40)
6711 {
6712 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6713 }
Leo Chang6f8870f2013-03-26 18:11:36 -07006714 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006715 if (rate_flags & eHAL_TX_RATE_SGI)
6716 {
6717 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6718 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05306719
Jeff Johnson295189b2012-06-20 16:38:30 -07006720#ifdef LINKSPEED_DEBUG_ENABLED
6721 pr_info("Reporting MCS rate %d flags %x\n",
6722 sinfo->txrate.mcs,
6723 sinfo->txrate.flags );
6724#endif //LINKSPEED_DEBUG_ENABLED
6725 }
6726 }
6727 else
6728 {
6729 // report current rate instead of max rate
6730
6731 if (rate_flags & eHAL_TX_RATE_LEGACY)
6732 {
6733 //provide to the UI in units of 100kbps
6734 sinfo->txrate.legacy = myRate;
6735#ifdef LINKSPEED_DEBUG_ENABLED
6736 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
6737#endif //LINKSPEED_DEBUG_ENABLED
6738 }
6739 else
6740 {
6741 //must be MCS
6742 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
Leo Chang6f8870f2013-03-26 18:11:36 -07006743#ifdef WLAN_FEATURE_11AC
6744 sinfo->txrate.nss = 1;
6745 if (rate_flags & eHAL_TX_RATE_VHT80)
6746 {
6747 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
6748 }
6749 else
6750#endif /* WLAN_FEATURE_11AC */
6751 {
6752 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6753 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006754 if (rate_flags & eHAL_TX_RATE_SGI)
6755 {
6756 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6757 }
6758 if (rate_flags & eHAL_TX_RATE_HT40)
6759 {
6760 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6761 }
Leo Chang6f8870f2013-03-26 18:11:36 -07006762#ifdef WLAN_FEATURE_11AC
6763 else if (rate_flags & eHAL_TX_RATE_VHT80)
6764 {
6765 sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
6766 }
6767#endif /* WLAN_FEATURE_11AC */
Jeff Johnson295189b2012-06-20 16:38:30 -07006768#ifdef LINKSPEED_DEBUG_ENABLED
6769 pr_info("Reporting actual MCS rate %d flags %x\n",
6770 sinfo->txrate.mcs,
6771 sinfo->txrate.flags );
6772#endif //LINKSPEED_DEBUG_ENABLED
6773 }
6774 }
6775 sinfo->filled |= STATION_INFO_TX_BITRATE;
6776
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006777 sinfo->tx_packets =
6778 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
6779 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
6780 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
6781 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
6782
6783 sinfo->tx_retries =
6784 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
6785 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
6786 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
6787 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
6788
6789 sinfo->tx_failed =
6790 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
6791 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
6792 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
6793 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
6794
6795 sinfo->filled |=
6796 STATION_INFO_TX_PACKETS |
6797 STATION_INFO_TX_RETRIES |
6798 STATION_INFO_TX_FAILED;
6799
6800 EXIT();
6801 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006802}
6803
6804static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
Sameer Thalappilc9f26e92013-06-07 10:11:06 -07006805 struct net_device *dev, bool mode, int timeout)
Jeff Johnson295189b2012-06-20 16:38:30 -07006806{
6807 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05306808 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07006809 VOS_STATUS vos_status;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306810 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006811
Jeff Johnsone7245742012-09-05 17:12:55 -07006812 ENTER();
6813
Jeff Johnson295189b2012-06-20 16:38:30 -07006814 if (NULL == pAdapter)
6815 {
6816 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6817 return -ENODEV;
6818 }
6819
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05306820 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306821 status = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05306822
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306823 if (0 != status)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306824 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306825 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6826 "%s: HDD context is not valid", __func__);
6827 return status;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306828 }
6829
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05306830 if ((DRIVER_POWER_MODE_AUTO == !mode) &&
6831 (TRUE == pHddCtx->hdd_wlan_suspended) &&
6832 (pHddCtx->cfg_ini->fhostArpOffload) &&
6833 (eConnectionState_Associated ==
6834 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
6835 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05306836 vos_status = hdd_conf_arp_offload(pAdapter, TRUE);
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05306837 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6838 {
6839 hddLog(VOS_TRACE_LEVEL_INFO,
6840 "%s:Failed to enable ARPOFFLOAD Feature %d\n",
6841 __func__, vos_status);
6842 }
6843 }
6844
Jeff Johnson295189b2012-06-20 16:38:30 -07006845 /**The get power cmd from the supplicant gets updated by the nl only
6846 *on successful execution of the function call
6847 *we are oppositely mapped w.r.t mode in the driver
6848 **/
6849 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
6850
Jeff Johnsone7245742012-09-05 17:12:55 -07006851 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006852 if (VOS_STATUS_E_FAILURE == vos_status)
6853 {
6854 return -EINVAL;
6855 }
6856 return 0;
6857}
6858
6859
6860#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6861static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
6862 struct net_device *netdev,
6863 u8 key_index)
6864{
Jeff Johnsone7245742012-09-05 17:12:55 -07006865 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006866 return 0;
6867}
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306868#endif //LINUX_VERSION_CODE
Jeff Johnson295189b2012-06-20 16:38:30 -07006869
6870#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
6871static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6872 struct net_device *dev,
6873 struct ieee80211_txq_params *params)
6874{
Jeff Johnsone7245742012-09-05 17:12:55 -07006875 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006876 return 0;
6877}
6878#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6879static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6880 struct ieee80211_txq_params *params)
6881{
Jeff Johnsone7245742012-09-05 17:12:55 -07006882 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006883 return 0;
6884}
6885#endif //LINUX_VERSION_CODE
6886
6887static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
6888 struct net_device *dev, u8 *mac)
6889{
6890 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306891 hdd_context_t *pHddCtx;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006892 VOS_STATUS vos_status;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306893 int status;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006894 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006895
Jeff Johnsone7245742012-09-05 17:12:55 -07006896 ENTER();
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306897 if ( NULL == pAdapter )
Jeff Johnson295189b2012-06-20 16:38:30 -07006898 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306899 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006900 return -EINVAL;
6901 }
6902
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306903 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6904 status = wlan_hdd_validate_context(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006905
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306906 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006907 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306908 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6909 "%s: HDD context is not valid", __func__);
6910 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006911 }
6912
Jeff Johnson295189b2012-06-20 16:38:30 -07006913 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006914 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006915 )
6916 {
6917 if( NULL == mac )
6918 {
6919 v_U16_t i;
6920 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
6921 {
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07006922 if ((pAdapter->aStaInfo[i].isUsed) &&
6923 (!pAdapter->aStaInfo[i].isDeauthInProgress))
Jeff Johnson295189b2012-06-20 16:38:30 -07006924 {
6925 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
6926 hddLog(VOS_TRACE_LEVEL_INFO,
6927 "%s: Delete STA with MAC::"
6928 "%02x:%02x:%02x:%02x:%02x:%02x",
6929 __func__,
6930 macAddr[0], macAddr[1], macAddr[2],
6931 macAddr[3], macAddr[4], macAddr[5]);
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07006932 vos_status = hdd_softap_sta_deauth(pAdapter, macAddr);
6933 if (VOS_IS_STATUS_SUCCESS(vos_status))
6934 pAdapter->aStaInfo[i].isDeauthInProgress = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006935 }
6936 }
6937 }
6938 else
6939 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006940
6941 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
6942 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6943 {
6944 hddLog(VOS_TRACE_LEVEL_INFO,
6945 "%s: Skip this DEL STA as this is not used::"
6946 "%02x:%02x:%02x:%02x:%02x:%02x",
6947 __func__,
6948 mac[0], mac[1], mac[2],
6949 mac[3], mac[4], mac[5]);
6950 return -ENOENT;
6951 }
6952
6953 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
6954 {
6955 hddLog(VOS_TRACE_LEVEL_INFO,
6956 "%s: Skip this DEL STA as deauth is in progress::"
6957 "%02x:%02x:%02x:%02x:%02x:%02x",
6958 __func__,
6959 mac[0], mac[1], mac[2],
6960 mac[3], mac[4], mac[5]);
6961 return -ENOENT;
6962 }
6963
6964 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
6965
Jeff Johnson295189b2012-06-20 16:38:30 -07006966 hddLog(VOS_TRACE_LEVEL_INFO,
6967 "%s: Delete STA with MAC::"
6968 "%02x:%02x:%02x:%02x:%02x:%02x",
6969 __func__,
6970 mac[0], mac[1], mac[2],
6971 mac[3], mac[4], mac[5]);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006972
6973 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
6974 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6975 {
6976 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
6977 hddLog(VOS_TRACE_LEVEL_INFO,
6978 "%s: STA removal failed for ::"
6979 "%02x:%02x:%02x:%02x:%02x:%02x",
6980 __func__,
6981 mac[0], mac[1], mac[2],
6982 mac[3], mac[4], mac[5]);
6983 return -ENOENT;
6984 }
6985
Jeff Johnson295189b2012-06-20 16:38:30 -07006986 }
6987 }
6988
6989 EXIT();
6990
6991 return 0;
6992}
6993
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006994static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
6995 struct net_device *dev, u8 *mac, struct station_parameters *params)
6996{
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006997 int status = -EPERM;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006998#ifdef FEATURE_WLAN_TDLS
6999 u32 mask, set;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007000 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007001 mask = params->sta_flags_mask;
7002
7003 set = params->sta_flags_set;
7004
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007005#ifdef WLAN_FEATURE_TDLS_DEBUG
7006 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7007 "%s: mask 0x%x set 0x%x " MAC_ADDRESS_STR,
7008 __func__, mask, set, MAC_ADDR_ARRAY(mac));
7009#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007010
7011 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
7012 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08007013 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007014 }
7015 }
7016#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007017 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07007018}
7019
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007020
7021#ifdef FEATURE_WLAN_LFR
7022static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07007023 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007024{
7025#define MAX_PMKSAIDS_IN_CACHE 8
7026 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307027 static tANI_U32 i; // HDD Local Cache index
7028 tANI_U32 j=0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007029 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7030 tHalHandle halHandle;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307031 eHalStatus result;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307032 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007033 tANI_U8 BSSIDMatched = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307034 hdd_context_t *pHddCtx;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307035
Jeff Johnsone7245742012-09-05 17:12:55 -07007036 ENTER();
7037
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307038 // Validate pAdapter
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307039 if ( NULL == pAdapter )
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007040 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307041 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007042 return -EINVAL;
7043 }
7044
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307045 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7046 status = wlan_hdd_validate_context(pHddCtx);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007047
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307048 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007049 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307050 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7051 "%s: HDD context is not valid", __func__);
7052 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007053 }
7054
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307055 // Retrieve halHandle
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007056 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
7057
7058 for (j = 0; j < i; j++)
7059 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307060 if(vos_mem_compare(PMKIDCache[j].BSSID,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007061 pmksa->bssid, WNI_CFG_BSSID_LEN))
7062 {
7063 /* BSSID matched previous entry. Overwrite it. */
7064 BSSIDMatched = 1;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307065 vos_mem_copy(PMKIDCache[j].BSSID,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007066 pmksa->bssid, WNI_CFG_BSSID_LEN);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307067 vos_mem_copy(PMKIDCache[j].PMKID,
7068 pmksa->pmkid,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007069 CSR_RSN_PMKID_SIZE);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307070 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007071 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007072 dump_bssid(pmksa->bssid);
7073 dump_pmkid(halHandle, pmksa->pmkid);
7074 break;
7075 }
7076 }
7077
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07007078 /* Check we compared all entries,if then take the first slot now */
7079 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
7080
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007081 if (!BSSIDMatched)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307082 {
7083 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
7084 vos_mem_copy(PMKIDCache[i].BSSID,
7085 pmksa->bssid, ETHER_ADDR_LEN);
7086 vos_mem_copy(PMKIDCache[i].PMKID,
7087 pmksa->pmkid,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007088 CSR_RSN_PMKID_SIZE);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307089 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007090 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007091 dump_bssid(pmksa->bssid);
7092 dump_pmkid(halHandle, pmksa->pmkid);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307093 // Increment the HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007094 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307095 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007096 }
7097
7098
7099 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307100 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007101 // __func__, i );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307102 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007103 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007104 // Finally set the PMKSA ID Cache in CSR
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307105 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
7106 PMKIDCache,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007107 i );
7108 return 0;
7109}
7110
7111
7112static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07007113 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007114{
Jeff Johnsone7245742012-09-05 17:12:55 -07007115 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007116 // TODO: Implement this later.
7117 return 0;
7118}
7119
7120static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
7121{
Jeff Johnsone7245742012-09-05 17:12:55 -07007122 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007123 // TODO: Implement this later.
7124 return 0;
7125}
7126#endif
7127
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007128#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307129static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007130 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
7131{
7132 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7133 hdd_station_ctx_t *pHddStaCtx;
7134
7135 if (NULL == pAdapter)
7136 {
7137 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
7138 return -ENODEV;
7139 }
7140
7141 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7142
7143 // Added for debug on reception of Re-assoc Req.
7144 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
7145 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307146 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007147 ftie->ie_len);
7148 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
7149 }
7150
7151#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307152 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007153 ftie->ie_len);
7154#endif
7155
7156 // Pass the received FT IEs to SME
Gopichand Nakkala356fb102013-03-06 12:34:04 +05307157 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
7158 (const u8 *)ftie->ie,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007159 ftie->ie_len);
7160 return 0;
7161}
7162#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007163
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307164#ifdef FEATURE_WLAN_SCAN_PNO
7165
7166void hdd_cfg80211_sched_scan_done_callback(void *callbackContext,
7167 tSirPrefNetworkFoundInd *pPrefNetworkFoundInd)
7168{
7169 int ret;
7170 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
7171 hdd_context_t *pHddCtx;
7172
7173 if (NULL == pAdapter)
7174 {
7175 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7176 "%s: HDD adapter is Null", __func__);
7177 return ;
7178 }
7179
7180 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7181 if (NULL == pHddCtx)
7182 {
7183 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7184 "%s: HDD context is Null!!!", __func__);
7185 return ;
7186 }
7187
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307188 spin_lock(&pHddCtx->schedScan_lock);
7189 if (TRUE == pHddCtx->isWiphySuspended)
7190 {
7191 pHddCtx->isSchedScanUpdatePending = TRUE;
7192 spin_unlock(&pHddCtx->schedScan_lock);
7193 hddLog(VOS_TRACE_LEVEL_INFO,
7194 "%s: Update cfg80211 scan database after it resume", __func__);
7195 return ;
7196 }
7197 spin_unlock(&pHddCtx->schedScan_lock);
7198
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307199 ret = wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter);
7200
7201 if (0 > ret)
7202 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
7203
7204 cfg80211_sched_scan_results(pHddCtx->wiphy);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307205 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7206 "%s: cfg80211 scan result database updated", __func__);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307207}
7208
7209/*
7210 * FUNCTION: wlan_hdd_cfg80211_sched_scan_start
7211 * NL interface to enable PNO
7212 */
7213static int wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy,
7214 struct net_device *dev, struct cfg80211_sched_scan_request *request)
7215{
7216 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7217 tpSirPNOScanReq pPnoRequest = NULL;
7218 hdd_context_t *pHddCtx;
7219 tHalHandle hHal;
Madan Mohan Koyyalamudi1d16f462013-08-27 16:25:34 +05307220 v_U32_t i, indx, num_ch, tempInterval;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307221 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
7222 u8 channels_allowed[WNI_CFG_VALID_CHANNEL_LIST_LEN];
7223 v_U32_t num_channels_allowed = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7224 eHalStatus status = eHAL_STATUS_FAILURE;
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307225 int ret = 0;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307226
7227 if (NULL == pAdapter)
7228 {
7229 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7230 "%s: HDD adapter is Null", __func__);
7231 return -ENODEV;
7232 }
7233
7234 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307235 ret = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307236
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307237 if (0 != ret)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307238 {
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05307239 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7240 "%s: HDD context is not valid", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307241 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307242 }
7243
7244 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
7245 if (NULL == hHal)
7246 {
7247 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7248 "%s: HAL context is Null!!!", __func__);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307249 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307250 }
7251
7252 pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq));
7253 if (NULL == pPnoRequest)
7254 {
7255 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7256 "%s: vos_mem_malloc failed", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307257 return -ENOMEM;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307258 }
7259
7260 pPnoRequest->enable = 1; /*Enable PNO */
7261 pPnoRequest->ucNetworksCount = request->n_match_sets;
7262
7263 if (( !pPnoRequest->ucNetworksCount ) ||
7264 ( pPnoRequest->ucNetworksCount > SIR_PNO_MAX_SUPP_NETWORKS ))
7265 {
7266 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7267 "Network input is not correct");
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307268 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307269 goto error;
7270 }
7271
7272 if ( SIR_PNO_MAX_NETW_CHANNELS_EX < request->n_channels )
7273 {
7274 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7275 "Incorrect number of channels");
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307276 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307277 goto error;
7278 }
7279
7280 /* Framework provides one set of channels(all)
7281 * common for all saved profile */
7282 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
7283 channels_allowed, &num_channels_allowed))
7284 {
7285 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7286 "%s: failed to get valid channel list", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307287 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307288 goto error;
7289 }
7290 /* Checking each channel against allowed channel list */
7291 num_ch = 0;
7292 for (i = 0; i < request->n_channels; i++)
7293 {
7294 for (indx = 0; indx < num_channels_allowed; indx++)
7295 {
7296 if (request->channels[i]->hw_value == channels_allowed[indx])
7297 {
7298 valid_ch[num_ch++] = request->channels[i]->hw_value;
7299 break ;
7300 }
7301 }
7302 }
7303
7304 /* Filling per profile params */
7305 for (i = 0; i < pPnoRequest->ucNetworksCount; i++)
7306 {
7307 pPnoRequest->aNetworks[i].ssId.length =
7308 request->match_sets[i].ssid.ssid_len;
7309
7310 if (( 0 == pPnoRequest->aNetworks[i].ssId.length ) ||
7311 ( pPnoRequest->aNetworks[i].ssId.length > 32 ) )
7312 {
7313 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7314 "SSID Len %d is not correct for network %d",
7315 pPnoRequest->aNetworks[i].ssId.length, i);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307316 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307317 goto error;
7318 }
7319
7320 memcpy(pPnoRequest->aNetworks[i].ssId.ssId,
7321 request->match_sets[i].ssid.ssid,
7322 request->match_sets[i].ssid.ssid_len);
7323 pPnoRequest->aNetworks[i].authentication = 0; /*eAUTH_TYPE_ANY*/
7324 pPnoRequest->aNetworks[i].encryption = 0; /*eED_ANY*/
7325 pPnoRequest->aNetworks[i].bcastNetwType = 0; /*eBCAST_UNKNOWN*/
7326
7327 /*Copying list of valid channel into request */
7328 memcpy(pPnoRequest->aNetworks[i].aChannels, valid_ch, num_ch);
7329 pPnoRequest->aNetworks[i].ucChannelCount = num_ch;
7330
7331 pPnoRequest->aNetworks[i].rssiThreshold = 0; //Default value
7332 }
7333
Madan Mohan Koyyalamudi1d16f462013-08-27 16:25:34 +05307334 /* Driver gets only one time interval which is hardcoded in
7335 * supplicant for 10000ms. Taking power consumption into account 6 timers
7336 * will be used, Timervalue is increased exponentially i.e 10,20,40,
7337 * 80,160,320 secs. And number of scan cycle for each timer
7338 * is configurable through INI param gPNOScanTimerRepeatValue.
7339 * If it is set to 0 only one timer will be used and PNO scan cycle
7340 * will be repeated after each interval specified by supplicant
7341 * till PNO is disabled.
7342 */
7343 if (0 == pHddCtx->cfg_ini->configPNOScanTimerRepeatValue)
7344 pPnoRequest->scanTimers.ucScanTimersCount = HDD_PNO_SCAN_TIMERS_SET_ONE;
7345 else
7346 pPnoRequest->scanTimers.ucScanTimersCount =
7347 HDD_PNO_SCAN_TIMERS_SET_MULTIPLE;
7348
7349 tempInterval = (request->interval)/1000;
7350 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7351 "Base scan interval = %d PNOScanTimerRepeatValue = %d",
7352 tempInterval, pHddCtx->cfg_ini->configPNOScanTimerRepeatValue);
7353 for ( i = 0; i < pPnoRequest->scanTimers.ucScanTimersCount; i++)
7354 {
7355 pPnoRequest->scanTimers.aTimerValues[i].uTimerRepeat =
7356 pHddCtx->cfg_ini->configPNOScanTimerRepeatValue;
7357 pPnoRequest->scanTimers.aTimerValues[i].uTimerValue = tempInterval;
7358 tempInterval *= 2;
7359 }
7360 //Repeat last timer until pno disabled.
7361 pPnoRequest->scanTimers.aTimerValues[i-1].uTimerRepeat = 0;
7362
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307363 pPnoRequest->modePNO = SIR_PNO_MODE_ON_SUSPEND;
7364
7365 status = sme_SetPreferredNetworkList(WLAN_HDD_GET_HAL_CTX(pAdapter),
7366 pPnoRequest, pAdapter->sessionId,
7367 hdd_cfg80211_sched_scan_done_callback, pAdapter);
7368 if (eHAL_STATUS_SUCCESS != status)
7369 {
7370 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7371 "Failed to enable PNO");
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307372 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307373 goto error;
7374 }
7375
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307376 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7377 "PNO scanRequest offloaded");
7378
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307379error:
7380 vos_mem_free(pPnoRequest);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307381 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307382}
7383
7384/*
7385 * FUNCTION: wlan_hdd_cfg80211_sched_scan_stop
7386 * NL interface to disable PNO
7387 */
7388static int wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy,
7389 struct net_device *dev)
7390{
7391 eHalStatus status = eHAL_STATUS_FAILURE;
7392 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7393 hdd_context_t *pHddCtx;
7394 tHalHandle hHal;
7395 tpSirPNOScanReq pPnoRequest = NULL;
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307396 int ret = 0;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307397
7398 ENTER();
7399
7400 if (NULL == pAdapter)
7401 {
7402 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7403 "%s: HDD adapter is Null", __func__);
7404 return -ENODEV;
7405 }
7406
7407 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307408
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307409 if (NULL == pHddCtx)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307410 {
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05307411 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307412 "%s: HDD context is Null", __func__);
7413 return -ENODEV;
7414 }
7415
7416 /* The return 0 is intentional when isLogpInProgress and
7417 * isLoadUnloadInProgress. We did observe a crash due to a return of
7418 * failure in sched_scan_stop , especially for a case where the unload
7419 * of the happens at the same time. The function __cfg80211_stop_sched_scan
7420 * was clearing rdev->sched_scan_req only when the sched_scan_stop returns
7421 * success. If it returns a failure , then its next invocation due to the
7422 * clean up of the second interface will have the dev pointer corresponding
7423 * to the first one leading to a crash.
7424 */
7425 if (pHddCtx->isLogpInProgress)
7426 {
7427 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7428 "%s: LOGP in Progress. Ignore!!!", __func__);
7429 return ret;
7430 }
7431
7432 if (pHddCtx->isLoadUnloadInProgress)
7433 {
7434 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7435 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
7436 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307437 }
7438
7439 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
7440 if (NULL == hHal)
7441 {
7442 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7443 "%s: HAL context is Null!!!", __func__);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307444 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307445 }
7446
7447 pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq));
7448 if (NULL == pPnoRequest)
7449 {
7450 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7451 "%s: vos_mem_malloc failed", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307452 return -ENOMEM;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307453 }
7454
7455 memset(pPnoRequest, 0, sizeof (tSirPNOScanReq));
7456 pPnoRequest->enable = 0; /* Disable PNO */
7457 pPnoRequest->ucNetworksCount = 0;
7458
7459 status = sme_SetPreferredNetworkList(hHal, pPnoRequest,
7460 pAdapter->sessionId,
7461 NULL, pAdapter);
7462 if (eHAL_STATUS_SUCCESS != status)
7463 {
7464 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7465 "Failed to disabled PNO");
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307466 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307467 }
7468
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307469 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7470 "%s: PNO scan disabled", __func__);
7471
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307472 vos_mem_free(pPnoRequest);
7473
7474 EXIT();
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307475 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307476}
7477
7478#endif /*FEATURE_WLAN_SCAN_PNO*/
7479
7480
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007481#ifdef FEATURE_WLAN_TDLS
7482static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
7483 u8 *peer, u8 action_code, u8 dialog_token,
7484 u16 status_code, const u8 *buf, size_t len)
7485{
7486
7487 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7488 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007489 u8 peerMac[6];
7490 VOS_STATUS status;
Gopichand Nakkala05922802013-03-14 12:23:19 -07007491 int max_sta_failed = 0;
Hoonki Leea34dd892013-02-05 22:56:02 -08007492 int responder;
Hoonki Leed37cbb32013-04-20 00:31:14 -07007493 long rc;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007494
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007495 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007496 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307497 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007498 "Invalid arguments");
7499 return -EINVAL;
7500 }
7501
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08007502 if (pHddCtx->isLogpInProgress)
7503 {
7504 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7505 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07007506 wlan_hdd_tdls_set_link_status(pAdapter, peer, eTDLS_LINK_IDLE);
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08007507 return -EBUSY;
7508 }
7509
Hoonki Lee27511902013-03-14 18:19:06 -07007510 if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007511 {
Hoonki Lee27511902013-03-14 18:19:06 -07007512 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
7513 "%s: TDLS mode is disabled OR not enabled in FW."
7514 MAC_ADDRESS_STR " action %d declined.",
7515 __func__, MAC_ADDR_ARRAY(peer), action_code);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007516 return -ENOTSUPP;
7517 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08007518
Hoonki Lee27511902013-03-14 18:19:06 -07007519 /* other than teardown frame, other mgmt frames are not sent if disabled */
7520 if (SIR_MAC_TDLS_TEARDOWN != action_code)
7521 {
7522 /* if tdls_mode is disabled to respond to peer's request */
7523 if (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode)
7524 {
7525 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
7526 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07007527 " TDLS mode is disabled. action %d declined.",
7528 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee27511902013-03-14 18:19:06 -07007529
7530 return -ENOTSUPP;
7531 }
7532 }
7533
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007534 if (WLAN_IS_TDLS_SETUP_ACTION(action_code))
7535 {
Hoonki Leefb8df672013-04-10 18:20:34 -07007536 if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, peer, TRUE, TRUE))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007537 {
7538 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007539 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07007540 " TDLS setup is ongoing. action %d declined.",
7541 __func__, MAC_ADDR_ARRAY(peer), action_code);
7542 return -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007543 }
7544 }
7545
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007546 if (SIR_MAC_TDLS_SETUP_REQ == action_code ||
7547 SIR_MAC_TDLS_SETUP_RSP == action_code )
Lee Hoonkic1262f22013-01-24 21:59:00 -08007548 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007549 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
Lee Hoonkic1262f22013-01-24 21:59:00 -08007550 {
7551 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
7552 we return error code at 'add_station()'. Hence we have this
7553 check again in addtion to add_station().
7554 Anyway, there is no hard to double-check. */
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007555 if (SIR_MAC_TDLS_SETUP_REQ == action_code)
Lee Hoonkic1262f22013-01-24 21:59:00 -08007556 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007557 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7558 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07007559 " TDLS Max peer already connected. action %d declined.",
7560 __func__, MAC_ADDR_ARRAY(peer), action_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07007561 goto error;
Lee Hoonkic1262f22013-01-24 21:59:00 -08007562 }
7563 else
7564 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007565 /* maximum reached. tweak to send error code to peer and return
7566 error code to supplicant */
Lee Hoonkic1262f22013-01-24 21:59:00 -08007567 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007568 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7569 "%s: " MAC_ADDRESS_STR
7570 " TDLS Max peer already connected send response status %d",
7571 __func__, MAC_ADDR_ARRAY(peer), status_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07007572 max_sta_failed = -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007573 /* fall through to send setup resp with failure status
7574 code */
Lee Hoonkic1262f22013-01-24 21:59:00 -08007575 }
7576 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007577 else
7578 {
7579 hddTdlsPeer_t *pTdlsPeer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007580 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007581 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007582 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007583 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07007584 "%s:" MAC_ADDRESS_STR " already connected. action %d declined.",
7585 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007586 return -EPERM;
7587 }
7588 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08007589 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007590 vos_mem_copy(peerMac, peer, 6);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007591
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007592#ifdef WLAN_FEATURE_TDLS_DEBUG
7593 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007594 "%s: " MAC_ADDRESS_STR " action %d, dialog_token %d status %d, len = %d",
7595 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
7596 action_code, dialog_token, status_code, len);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007597#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007598
Hoonki Leea34dd892013-02-05 22:56:02 -08007599 /*Except teardown responder will not be used so just make 0*/
7600 responder = 0;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007601 if (SIR_MAC_TDLS_TEARDOWN == action_code)
Hoonki Leea34dd892013-02-05 22:56:02 -08007602 {
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -07007603
7604 hddTdlsPeer_t *pTdlsPeer;
7605 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peerMac);
7606
7607 if(pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
7608 responder = pTdlsPeer->is_responder;
7609 else
Hoonki Leea34dd892013-02-05 22:56:02 -08007610 {
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -07007611 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7612 "%s: " MAC_ADDRESS_STR " peer doesn't exist or not connected %d dialog_token %d status %d, len = %d",
7613 __func__, MAC_ADDR_ARRAY(peer), (NULL == pTdlsPeer) ? -1 : pTdlsPeer->link_status,
7614 dialog_token, status_code, len);
7615 return -EPERM;
Hoonki Leea34dd892013-02-05 22:56:02 -08007616 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007617 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007618
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05307619 /* For explicit trigger of DIS_REQ come out of BMPS for
7620 successfully receiving DIS_RSP from peer. */
Hoonki Lee14621352013-04-16 17:51:19 -07007621 if ((SIR_MAC_TDLS_SETUP_RSP == action_code) ||
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05307622 (SIR_MAC_TDLS_DIS_RSP == action_code) ||
7623 (SIR_MAC_TDLS_DIS_REQ == action_code))
Hoonki Lee14621352013-04-16 17:51:19 -07007624 {
7625 if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter)))
7626 {
7627 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05307628 "%s: Sending frame action_code %u.Disable BMPS", __func__, action_code);
Hoonki Lee14621352013-04-16 17:51:19 -07007629 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
7630 }
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05307631 if (SIR_MAC_TDLS_DIS_REQ != action_code)
7632 wlan_hdd_tdls_set_cap(pAdapter, peerMac, eTDLS_CAP_SUPPORTED);
Hoonki Lee14621352013-04-16 17:51:19 -07007633 }
7634
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007635 /* make sure doesn't call send_mgmt() while it is pending */
7636 if (TDLS_CTX_MAGIC == pAdapter->mgmtTxCompletionStatus)
7637 {
7638 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7639 "%s: " MAC_ADDRESS_STR " action %d couldn't sent, as one is pending. return EBUSY\n",
7640 __func__, MAC_ADDR_ARRAY(peer), action_code);
7641 return -EBUSY;
7642 }
7643
7644 pAdapter->mgmtTxCompletionStatus = TDLS_CTX_MAGIC;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007645 INIT_COMPLETION(pAdapter->tdls_mgmt_comp);
7646
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007647 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
Hoonki Leea34dd892013-02-05 22:56:02 -08007648 peerMac, action_code, dialog_token, status_code, (tANI_U8 *)buf, len, responder);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007649
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007650 if (VOS_STATUS_SUCCESS != status)
7651 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007652 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7653 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007654 pAdapter->mgmtTxCompletionStatus = FALSE;
Hoonki Lee14621352013-04-16 17:51:19 -07007655 wlan_hdd_tdls_check_bmps(pAdapter);
7656 goto error;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007657 }
7658
Hoonki Leed37cbb32013-04-20 00:31:14 -07007659 rc = wait_for_completion_interruptible_timeout(&pAdapter->tdls_mgmt_comp,
7660 msecs_to_jiffies(WAIT_TIME_TDLS_MGMT));
7661
7662 if ((rc <= 0) || (TRUE != pAdapter->mgmtTxCompletionStatus))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007663 {
Hoonki Leed37cbb32013-04-20 00:31:14 -07007664 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7665 "%s: Mgmt Tx Completion failed status %ld TxCompletion %lu",
7666 __func__, rc, pAdapter->mgmtTxCompletionStatus);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007667 pAdapter->mgmtTxCompletionStatus = FALSE;
Hoonki Leed37cbb32013-04-20 00:31:14 -07007668 wlan_hdd_tdls_check_bmps(pAdapter);
7669 goto error;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007670 }
7671
Gopichand Nakkala05922802013-03-14 12:23:19 -07007672 if (max_sta_failed)
Hoonki Lee14621352013-04-16 17:51:19 -07007673 {
7674 wlan_hdd_tdls_check_bmps(pAdapter);
Gopichand Nakkala05922802013-03-14 12:23:19 -07007675 return max_sta_failed;
Hoonki Lee14621352013-04-16 17:51:19 -07007676 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007677
Hoonki Leea34dd892013-02-05 22:56:02 -08007678 if (SIR_MAC_TDLS_SETUP_RSP == action_code)
7679 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007680 wlan_hdd_tdls_set_responder(pAdapter, peerMac, TRUE);
Hoonki Leea34dd892013-02-05 22:56:02 -08007681 }
7682 else if (SIR_MAC_TDLS_SETUP_CNF == action_code)
7683 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007684 wlan_hdd_tdls_set_responder(pAdapter, peerMac, FALSE);
Hoonki Leea34dd892013-02-05 22:56:02 -08007685 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007686
7687 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07007688error:
7689 /* max_sta_failed ; we didn't set to CONNECTING for this case,
7690 because we already know that this transaction will be failed,
7691 but we weren't sure if supplicant call DISABLE_LINK or not. So,
7692 to be safe, do not change the state mahine.
7693 */
7694 if(max_sta_failed == 0 &&
7695 (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
7696 wlan_hdd_tdls_set_link_status(pAdapter, peerMac, eTDLS_LINK_IDLE);
7697 return -EPERM;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007698}
7699
7700static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
7701 u8 *peer, enum nl80211_tdls_operation oper)
7702{
7703 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7704 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307705 int status;
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007706#ifdef WLAN_FEATURE_TDLS_DEBUG
7707 const char *tdls_oper_str[]= {
7708 "NL80211_TDLS_DISCOVERY_REQ",
7709 "NL80211_TDLS_SETUP",
7710 "NL80211_TDLS_TEARDOWN",
7711 "NL80211_TDLS_ENABLE_LINK",
7712 "NL80211_TDLS_DISABLE_LINK",
Gopichand Nakkala29d00192013-06-20 19:03:52 +05307713 "NL80211_TDLS_UNKNOWN_OPER"};
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007714#endif
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007715 hddTdlsPeer_t *pTdlsPeer;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007716
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307717 if ( NULL == peer )
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007718 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007719 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Chilam Ngc4244af2013-04-01 15:37:32 -07007720 "%s: Invalid arguments", __func__);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007721 return -EINVAL;
7722 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007723
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307724 status = wlan_hdd_validate_context(pHddCtx);
7725
7726 if (0 != status)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08007727 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307728 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7729 "%s: HDD context is not valid", __func__);
7730 return status;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08007731 }
7732
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007733 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
7734
7735 if ( NULL == pTdlsPeer ) {
7736 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: " MAC_ADDRESS_STR " (oper %d) not exsting. ignored",
7737 __func__, MAC_ADDR_ARRAY(peer), (int)oper);
7738 return -EINVAL;
7739 }
7740
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007741#ifdef WLAN_FEATURE_TDLS_DEBUG
7742 if((int)oper > 4)
7743 oper = 5;
7744
7745 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007746 "%s: " MAC_ADDRESS_STR " link_status %d (%s) ", "tdls_oper",
7747 MAC_ADDR_ARRAY(peer), pTdlsPeer->link_status,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007748 tdls_oper_str[(int)oper]);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007749#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007750
7751 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007752 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007753 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007754 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Chilam Ngc4244af2013-04-01 15:37:32 -07007755 "TDLS Disabled in INI OR not enabled in FW. "
7756 "Cannot process TDLS commands");
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007757 return -ENOTSUPP;
7758 }
7759
7760 switch (oper) {
7761 case NL80211_TDLS_ENABLE_LINK:
7762 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007763 VOS_STATUS status;
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307764 tCsrTdlsLinkEstablishParams tdlsLinkEstablishParams;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007765
Gopichand Nakkala2f4a2822013-04-17 11:22:01 -07007766 if (!TDLS_STA_INDEX_VALID(pTdlsPeer->staId))
7767 {
7768 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Staion Index %u "
7769 MAC_ADDRESS_STR " failed",
7770 __func__, pTdlsPeer->staId, MAC_ADDR_ARRAY(peer));
7771 return -EINVAL;
7772 }
7773
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007774 if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status)
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007775 {
Gopichand Nakkala24be5312013-07-02 16:47:12 +05307776 long ret;
7777
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307778 if (0 != wlan_hdd_tdls_get_link_establish_params(pAdapter, peer,&tdlsLinkEstablishParams)) {
7779 return -EINVAL;
7780 }
7781 INIT_COMPLETION(pAdapter->tdls_link_establish_req_comp);
7782
7783 sme_SendTdlsLinkEstablishParams(WLAN_HDD_GET_HAL_CTX(pAdapter),
7784 pAdapter->sessionId, peer, &tdlsLinkEstablishParams);
7785 /* Send TDLS peer UAPSD capabilities to the firmware and
7786 * register with the TL on after the response for this operation
7787 * is received .
7788 */
Gopichand Nakkala24be5312013-07-02 16:47:12 +05307789 ret = wait_for_completion_interruptible_timeout(&pAdapter->tdls_link_establish_req_comp,
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307790 msecs_to_jiffies(WAIT_TIME_TDLS_LINK_ESTABLISH_REQ));
Gopichand Nakkala24be5312013-07-02 16:47:12 +05307791 if (ret <= 0)
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307792 {
7793 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7794 "%s: Link Establish Request Faled Status %ld",
Gopichand Nakkala24be5312013-07-02 16:47:12 +05307795 __func__, ret);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307796 return -EINVAL;
7797 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007798 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
Gopichand Nakkala471708b2013-06-04 20:03:01 +05307799 /* Mark TDLS client Authenticated .*/
7800 status = WLANTL_ChangeSTAState( pHddCtx->pvosContext,
7801 pTdlsPeer->staId,
7802 WLANTL_STA_AUTHENTICATED);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007803 if (VOS_STATUS_SUCCESS == status)
7804 {
Hoonki Lee14621352013-04-16 17:51:19 -07007805 if (pTdlsPeer->is_responder == 0)
7806 {
7807 v_U8_t staId = (v_U8_t)pTdlsPeer->staId;
7808
7809 wlan_hdd_tdls_timer_restart(pAdapter,
7810 &pTdlsPeer->initiatorWaitTimeoutTimer,
7811 WAIT_TIME_TDLS_INITIATOR);
7812 /* suspend initiator TX until it receives direct packet from the
7813 reponder or WAIT_TIME_TDLS_INITIATOR timer expires */
7814 WLANTL_SuspendDataTx( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
7815 &staId, NULL);
7816 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007817 wlan_hdd_tdls_increment_peer_count(pAdapter);
7818 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007819 wlan_hdd_tdls_check_bmps(pAdapter);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307820
7821 /* Update TL about the UAPSD masks , to route the packets to firmware */
Gopichand Nakkala574f6d12013-06-27 19:38:43 +05307822 if ((TRUE == pHddCtx->cfg_ini->fEnableTDLSBufferSta)
7823 || pHddCtx->cfg_ini->fTDLSUapsdMask )
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307824 {
Gopichand Nakkala574f6d12013-06-27 19:38:43 +05307825 int ac;
7826 uint8 ucAc[4] = { WLANTL_AC_VO,
7827 WLANTL_AC_VI,
7828 WLANTL_AC_BK,
7829 WLANTL_AC_BE };
7830 uint8 tlTid[4] = { 7, 5, 2, 3 } ;
7831 for(ac=0; ac < 4; ac++)
7832 {
7833 status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
7834 pTdlsPeer->staId, ucAc[ac],
7835 tlTid[ac], tlTid[ac], 0, 0,
7836 WLANTL_BI_DIR );
7837 }
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307838 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007839 }
7840
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007841 }
7842 break;
7843 case NL80211_TDLS_DISABLE_LINK:
Lee Hoonkic1262f22013-01-24 21:59:00 -08007844 {
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007845 if(TDLS_STA_INDEX_VALID(pTdlsPeer->staId))
Lee Hoonkic1262f22013-01-24 21:59:00 -08007846 {
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007847 long status;
7848
7849 INIT_COMPLETION(pAdapter->tdls_del_station_comp);
7850
Lee Hoonkic1262f22013-01-24 21:59:00 -08007851 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
7852 pAdapter->sessionId, peer );
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007853
7854 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_del_station_comp,
7855 msecs_to_jiffies(WAIT_TIME_TDLS_DEL_STA));
7856 if (status <= 0)
7857 {
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007858 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_IDLE);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007859 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7860 "%s: Del station failed status %ld",
7861 __func__, status);
7862 return -EPERM;
7863 }
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007864 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_IDLE);
Lee Hoonkic1262f22013-01-24 21:59:00 -08007865 }
7866 else
7867 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007868 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7869 "%s: TDLS Peer Station doesn't exist.", __func__);
Lee Hoonkic1262f22013-01-24 21:59:00 -08007870 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08007871 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007872 break;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007873 case NL80211_TDLS_TEARDOWN:
7874 case NL80211_TDLS_SETUP:
7875 case NL80211_TDLS_DISCOVERY_REQ:
7876 /* We don't support in-driver setup/teardown/discovery */
7877 return -ENOTSUPP;
7878 default:
7879 return -ENOTSUPP;
7880 }
7881 return 0;
7882}
Chilam NG571c65a2013-01-19 12:27:36 +05307883
7884int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
7885 struct net_device *dev, u8 *peer)
7886{
7887 hddLog(VOS_TRACE_LEVEL_INFO, "tdls send discover req: %x %x %x %x %x %x",
7888 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5]);
7889
7890 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
7891 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
7892}
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007893#endif
7894
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05307895#ifdef WLAN_FEATURE_GTK_OFFLOAD
7896/*
7897 * FUNCTION: wlan_hdd_cfg80211_update_replayCounterCallback
7898 * Callback rountine called upon receiving response for
7899 * get offload info
7900 */
7901void wlan_hdd_cfg80211_update_replayCounterCallback(void *callbackContext,
7902 tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoRsp)
7903{
7904
7905 hdd_adapter_t *pAdapter = (hdd_adapter_t *)callbackContext;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05307906 tANI_U8 tempReplayCounter[8];
7907 hdd_station_ctx_t *pHddStaCtx;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05307908
7909 ENTER();
7910
7911 if (NULL == pAdapter)
7912 {
7913 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7914 "%s: HDD adapter is Null", __func__);
7915 return ;
7916 }
7917
7918 if (NULL == pGtkOffloadGetInfoRsp)
7919 {
7920 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7921 "%s: pGtkOffloadGetInfoRsp is Null", __func__);
7922 return ;
7923 }
7924
7925 if (VOS_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus)
7926 {
7927 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7928 "%s: wlan Failed to get replay counter value",
7929 __func__);
7930 return ;
7931 }
7932
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05307933 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7934 /* Update replay counter */
7935 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
7936 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
7937
7938 {
7939 /* changing from little to big endian since supplicant
7940 * works on big endian format
7941 */
7942 int i;
7943 tANI_U8 *p = (tANI_U8 *)&pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
7944
7945 for (i = 0; i < 8; i++)
7946 {
7947 tempReplayCounter[7-i] = (tANI_U8)p[i];
7948 }
7949 }
7950
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05307951 /* Update replay counter to NL */
7952 cfg80211_gtk_rekey_notify(pAdapter->dev, pGtkOffloadGetInfoRsp->bssId,
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05307953 tempReplayCounter, GFP_KERNEL);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05307954}
7955
7956/*
7957 * FUNCTION: wlan_hdd_cfg80211_set_rekey_data
7958 * This function is used to offload GTK rekeying job to the firmware.
7959 */
7960int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
7961 struct cfg80211_gtk_rekey_data *data)
7962{
7963 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7964 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
7965 hdd_station_ctx_t *pHddStaCtx;
7966 tHalHandle hHal;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307967 int result;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05307968 tSirGtkOffloadParams hddGtkOffloadReqParams;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05307969 eHalStatus status = eHAL_STATUS_FAILURE;
7970
7971 ENTER();
7972
7973 if (NULL == pAdapter)
7974 {
7975 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7976 "%s: HDD adapter is Null", __func__);
7977 return -ENODEV;
7978 }
7979
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307980 result = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05307981
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307982 if (0 != result)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05307983 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307984 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7985 "%s: HDD context is not valid", __func__);
7986 return result;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05307987 }
7988
7989 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7990 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
7991 if (NULL == hHal)
7992 {
7993 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7994 "%s: HAL context is Null!!!", __func__);
7995 return -EAGAIN;
7996 }
7997
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05307998 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
7999 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck, NL80211_KCK_LEN);
8000 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek, NL80211_KEK_LEN);
8001 memcpy(pHddStaCtx->gtkOffloadReqParams.bssId, &pHddStaCtx->conn_info.bssId,
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308002 WNI_CFG_BSSID_LEN);
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308003 {
8004 /* changing from big to little endian since driver
8005 * works on little endian format
8006 */
8007 tANI_U8 *p =
8008 (tANI_U8 *)&pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter;
8009 int i;
8010
8011 for (i = 0; i < 8; i++)
8012 {
8013 p[7-i] = data->replay_ctr[i];
8014 }
8015 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308016
8017 if (TRUE == pHddCtx->hdd_wlan_suspended)
8018 {
8019 /* if wlan is suspended, enable GTK offload directly from here */
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308020 memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams,
8021 sizeof (tSirGtkOffloadParams));
8022 status = sme_SetGTKOffload(hHal, &hddGtkOffloadReqParams,
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308023 pAdapter->sessionId);
8024
8025 if (eHAL_STATUS_SUCCESS != status)
8026 {
8027 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8028 "%s: sme_SetGTKOffload failed, returned %d",
8029 __func__, status);
8030 return status;
8031 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308032 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8033 "%s: sme_SetGTKOffload successfull", __func__);
8034 }
8035 else
8036 {
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308037 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8038 "%s: wlan not suspended GTKOffload request is stored",
8039 __func__);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308040 }
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308041
8042 return eHAL_STATUS_SUCCESS;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308043}
8044#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
8045
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05308046/*
8047 * FUNCTION: wlan_hdd_cfg80211_set_mac_acl
8048 * This function is used to set access control policy
8049 */
8050static int wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
8051 struct net_device *dev, const struct cfg80211_acl_data *params)
8052{
8053 int i;
8054 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8055 hdd_hostapd_state_t *pHostapdState;
8056 tsap_Config_t *pConfig;
8057 v_CONTEXT_t pVosContext = NULL;
8058 hdd_context_t *pHddCtx;
8059 int status;
8060
8061 ENTER();
8062
8063 if (NULL == pAdapter)
8064 {
8065 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8066 "%s: HDD adapter is Null", __func__);
8067 return -ENODEV;
8068 }
8069
8070 if (NULL == params)
8071 {
8072 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8073 "%s: params is Null", __func__);
8074 return -EINVAL;
8075 }
8076
8077 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8078 status = wlan_hdd_validate_context(pHddCtx);
8079
8080 if (0 != status)
8081 {
8082 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8083 "%s: HDD context is not valid", __func__);
8084 return status;
8085 }
8086
8087 pVosContext = pHddCtx->pvosContext;
8088 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
8089
8090 if (NULL == pHostapdState)
8091 {
8092 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8093 "%s: pHostapdState is Null", __func__);
8094 return -EINVAL;
8095 }
8096
8097 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"acl policy: = %d"
8098 "no acl entries = %d", params->acl_policy, params->n_acl_entries);
8099
8100 if (WLAN_HDD_SOFTAP == pAdapter->device_mode)
8101 {
8102 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
8103
8104 /* default value */
8105 pConfig->num_accept_mac = 0;
8106 pConfig->num_deny_mac = 0;
8107
8108 /**
8109 * access control policy
8110 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
8111 * listed in hostapd.deny file.
8112 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
8113 * listed in hostapd.accept file.
8114 */
8115 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy)
8116 {
8117 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
8118 }
8119 else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED == params->acl_policy)
8120 {
8121 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
8122 }
8123 else
8124 {
8125 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8126 "%s:Acl Policy : %d is not supported",
8127 __func__, params->acl_policy);
8128 return -ENOTSUPP;
8129 }
8130
8131 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl)
8132 {
8133 pConfig->num_accept_mac = params->n_acl_entries;
8134 for (i = 0; i < params->n_acl_entries; i++)
8135 {
8136 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8137 "** Add ACL MAC entry %i in WhiletList :"
8138 MAC_ADDRESS_STR, i,
8139 MAC_ADDR_ARRAY(params->mac_addrs[i].addr));
8140
8141 vos_mem_copy(&pConfig->accept_mac[i], params->mac_addrs[i].addr,
8142 sizeof(qcmacaddr));
8143 }
8144 }
8145 else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl)
8146 {
8147 pConfig->num_deny_mac = params->n_acl_entries;
8148 for (i = 0; i < params->n_acl_entries; i++)
8149 {
8150 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8151 "** Add ACL MAC entry %i in BlackList :"
8152 MAC_ADDRESS_STR, i,
8153 MAC_ADDR_ARRAY(params->mac_addrs[i].addr));
8154
8155 vos_mem_copy(&pConfig->deny_mac[i], params->mac_addrs[i].addr,
8156 sizeof(qcmacaddr));
8157 }
8158 }
8159
8160 if (VOS_STATUS_SUCCESS != WLANSAP_SetMacACL(pVosContext, pConfig))
8161 {
8162 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8163 "%s: SAP Set Mac Acl fail", __func__);
8164 return -EINVAL;
8165 }
8166 }
8167 else
8168 {
8169 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8170 "%s: Invalid device_mode = %d",
8171 __func__, pAdapter->device_mode);
8172 return -EINVAL;
8173 }
8174
8175 return 0;
8176}
8177
Leo Chang9056f462013-08-01 19:21:11 -07008178#ifdef WLAN_NL80211_TESTMODE
8179#ifdef FEATURE_WLAN_LPHB
8180static void wlan_hdd_cfg80211_lphb_wait_timeout_ind_handler
8181(
8182 void *pAdapter,
8183 void *indCont
8184)
8185{
8186 tSirLPHBTimeoutInd *lphbTimeoutInd;
8187 struct sk_buff *skb;
8188
8189 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8190 "LPHB wait timeout indication arrived");
8191
8192 if (NULL == indCont)
8193 {
8194 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8195 "LPHB timeout, invalid argument");
8196 return;
8197 }
8198
8199 lphbTimeoutInd = (tSirLPHBTimeoutInd *)indCont;
8200 skb = cfg80211_testmode_alloc_event_skb(
8201 ((hdd_adapter_t *)pAdapter)->wdev.wiphy,
8202 sizeof(tSirLPHBTimeoutInd),
8203 GFP_ATOMIC);
8204 if (!skb)
8205 {
8206 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8207 "LPHB timeout, NL buffer alloc fail");
8208 return;
8209 }
8210
8211 NLA_PUT_U32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB);
8212 NLA_PUT_U32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbTimeoutInd->protocolType);
8213 NLA_PUT(skb, WLAN_HDD_TM_ATTR_DATA,
8214 sizeof(tSirLPHBTimeoutInd), lphbTimeoutInd);
8215 cfg80211_testmode_event(skb, GFP_ATOMIC);
8216 return;
8217
8218nla_put_failure:
8219 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8220 "NLA Put fail");
8221 kfree_skb(skb);
8222
8223 return;
8224}
8225#endif /* FEATURE_WLAN_LPHB */
8226
8227static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy, void *data, int len)
8228{
8229 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
8230 int err = 0;
8231#ifdef FEATURE_WLAN_LPHB
8232 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8233#endif /* FEATURE_WLAN_LPHB */
8234
8235 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data, len, wlan_hdd_tm_policy);
8236 if (err)
8237 {
8238 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8239 "%s Testmode INV ATTR", __func__);
8240 return err;
8241 }
8242
8243 if (!tb[WLAN_HDD_TM_ATTR_CMD])
8244 {
8245 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8246 "%s Testmode INV CMD", __func__);
8247 return -EINVAL;
8248 }
8249
8250 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]))
8251 {
8252#ifdef FEATURE_WLAN_LPHB
8253 /* Low Power Heartbeat configuration request */
8254 case WLAN_HDD_TM_CMD_WLAN_HB:
8255 {
8256 int buf_len;
8257 void *buf;
8258 tSirLPHBReq *hb_params = NULL;
8259
8260 if (!tb[WLAN_HDD_TM_ATTR_DATA])
8261 {
8262 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8263 "%s Testmode INV DATA", __func__);
8264 return -EINVAL;
8265 }
8266
8267 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
8268 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
8269 hb_params = (tSirLPHBReq *)vos_mem_malloc(sizeof(tSirLPHBReq));
8270 if (NULL == hb_params)
8271 {
8272 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8273 "%s Request Buffer Alloc Fail", __func__);
8274 return -EINVAL;
8275 }
8276
8277 vos_mem_copy(hb_params, buf, buf_len);
8278
8279 /* LPHB enable and disable request will send to FW
8280 * when host suspend and resume
8281 * host suspend -> enable LPHB
8282 * host resume -> disable LPHB
8283 * if host is not suspend, cache into HDD context
8284 * and when host goes to suspend, send request to FW */
8285 if ((LPHB_SET_EN_PARAMS_INDID == hb_params->cmd) &&
8286 (!pHddCtx->hdd_wlan_suspended))
8287 {
8288 /* Feature enable command cache into HDD context,
8289 * if WLAN is not suspend
8290 * When WLAN goes into suspend, send enable command to FW */
8291 pHddCtx->lphbEnableReq.enable =
8292 hb_params->params.lphbEnableReq.enable;
8293 pHddCtx->lphbEnableReq.item =
8294 hb_params->params.lphbEnableReq.item;
8295 pHddCtx->lphbEnableReq.session =
8296 hb_params->params.lphbEnableReq.session;
8297 vos_mem_free(hb_params);
8298 }
8299 else
8300 {
8301 eHalStatus smeStatus;
8302
8303 /* If WLAN is suspend state, send enable command immediately */
8304 smeStatus = sme_LPHBConfigReq((tHalHandle)(pHddCtx->hHal),
8305 hb_params,
8306 wlan_hdd_cfg80211_lphb_wait_timeout_ind_handler);
8307 if (eHAL_STATUS_SUCCESS != smeStatus)
8308 {
8309 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8310 "LPHB Config Fail, disable");
8311 pHddCtx->lphbEnableReq.enable = 0;
8312 vos_mem_free(hb_params);
8313 }
8314 }
8315 return 0;
8316 }
8317#endif /* FEATURE_WLAN_LPHB */
8318 default:
8319 return -EOPNOTSUPP;
8320 }
8321
8322 return err;
8323}
8324#endif /* CONFIG_NL80211_TESTMODE */
8325
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308326static int wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy,
8327 struct net_device *dev,
8328 int idx, struct survey_info *survey)
8329{
8330 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8331 hdd_context_t *pHddCtx;
Mihir Sheted9072e02013-08-21 17:02:29 +05308332 hdd_station_ctx_t *pHddStaCtx;
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308333 tHalHandle halHandle;
Mihir Sheted9072e02013-08-21 17:02:29 +05308334 v_U32_t channel = 0, freq = 0; /* Initialization Required */
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308335 v_S7_t snr,rssi;
8336 int status, i, j, filled = 0;
8337
8338 ENTER();
8339
8340
8341 if (NULL == pAdapter)
8342 {
8343 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8344 "%s: HDD adapter is Null", __func__);
8345 return -ENODEV;
8346 }
8347
8348 if (NULL == wiphy)
8349 {
8350 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8351 "%s: wiphy is Null", __func__);
8352 return -ENODEV;
8353 }
8354
8355 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8356 status = wlan_hdd_validate_context(pHddCtx);
8357
8358 if (0 != status)
8359 {
8360 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8361 "%s: HDD context is not valid", __func__);
8362 return status;
8363 }
8364
Mihir Sheted9072e02013-08-21 17:02:29 +05308365 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8366
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308367 if (0 == pHddCtx->cfg_ini->fEnableSNRMonitoring ||
Mihir Sheted9072e02013-08-21 17:02:29 +05308368 0 != pAdapter->survey_idx ||
8369 eConnectionState_Associated != pHddStaCtx->conn_info.connState)
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308370 {
8371 /* The survey dump ops when implemented completely is expected to
8372 * return a survey of all channels and the ops is called by the
8373 * kernel with incremental values of the argument 'idx' till it
8374 * returns -ENONET. But we can only support the survey for the
8375 * operating channel for now. survey_idx is used to track
8376 * that the ops is called only once and then return -ENONET for
8377 * the next iteration
8378 */
8379 pAdapter->survey_idx = 0;
8380 return -ENONET;
8381 }
8382
8383 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
8384
8385 wlan_hdd_get_snr(pAdapter, &snr);
8386 wlan_hdd_get_rssi(pAdapter, &rssi);
8387
8388 sme_GetOperationChannel(halHandle, &channel, pAdapter->sessionId);
8389 hdd_wlan_get_freq(channel, &freq);
8390
8391
8392 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
8393 {
8394 if (NULL == wiphy->bands[i])
8395 {
8396 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
8397 "%s: wiphy->bands[i] is NULL, i = %d", __func__, i);
8398 continue;
8399 }
8400
8401 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
8402 {
8403 struct ieee80211_supported_band *band = wiphy->bands[i];
8404
8405 if (band->channels[j].center_freq == (v_U16_t)freq)
8406 {
8407 survey->channel = &band->channels[j];
8408 /* The Rx BDs contain SNR values in dB for the received frames
8409 * while the supplicant expects noise. So we calculate and
8410 * return the value of noise (dBm)
8411 * SNR (dB) = RSSI (dBm) - NOISE (dBm)
8412 */
8413 survey->noise = rssi - snr;
8414 survey->filled = SURVEY_INFO_NOISE_DBM;
8415 filled = 1;
8416 }
8417 }
8418 }
8419
8420 if (filled)
8421 pAdapter->survey_idx = 1;
8422 else
8423 {
8424 pAdapter->survey_idx = 0;
8425 return -ENONET;
8426 }
8427
8428 return 0;
8429}
8430
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308431/*
8432 * FUNCTION: wlan_hdd_cfg80211_resume_wlan
8433 * this is called when cfg80211 driver resume
8434 * driver updates latest sched_scan scan result(if any) to cfg80211 database
8435 */
8436int wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
8437{
8438 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8439 hdd_adapter_t *pAdapter;
8440 hdd_adapter_list_node_t *pAdapterNode, *pNext;
8441 VOS_STATUS status = VOS_STATUS_SUCCESS;
8442
8443 ENTER();
8444
8445 if ( NULL == pHddCtx )
8446 {
8447 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8448 "%s: HddCtx validation failed", __func__);
8449 return 0;
8450 }
8451
8452 if (pHddCtx->isLogpInProgress)
8453 {
8454 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8455 "%s: LOGP in Progress. Ignore!!!", __func__);
8456 return 0;
8457 }
8458
8459 if (pHddCtx->isLoadUnloadInProgress)
8460 {
8461 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8462 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
8463 return 0;
8464 }
8465
8466 spin_lock(&pHddCtx->schedScan_lock);
8467 pHddCtx->isWiphySuspended = FALSE;
8468 if (TRUE != pHddCtx->isSchedScanUpdatePending)
8469 {
8470 spin_unlock(&pHddCtx->schedScan_lock);
8471 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8472 "%s: Return resume is not due to PNO indication", __func__);
8473 return 0;
8474 }
8475 // Reset flag to avoid updatating cfg80211 data old results again
8476 pHddCtx->isSchedScanUpdatePending = FALSE;
8477 spin_unlock(&pHddCtx->schedScan_lock);
8478
8479 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8480
8481 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
8482 {
8483 pAdapter = pAdapterNode->pAdapter;
8484 if ( (NULL != pAdapter) &&
8485 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
8486 {
8487 if (0 != wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter))
8488 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
8489 "%s: NO SCAN result", __func__);
8490 else
8491 cfg80211_sched_scan_results(pHddCtx->wiphy);
8492
8493 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8494 "%s : cfg80211 scan result database updated", __func__);
8495
8496 return 0;
8497
8498 }
8499 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8500 pAdapterNode = pNext;
8501 }
8502
8503 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8504 "%s: Failed to find Adapter", __func__);
8505 return 0;
8506}
8507
8508/*
8509 * FUNCTION: wlan_hdd_cfg80211_suspend_wlan
8510 * this is called when cfg80211 driver suspends
8511 */
8512int wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
8513 struct cfg80211_wowlan *wow)
8514{
8515 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8516
8517 ENTER();
8518 if (NULL == pHddCtx)
8519 {
8520 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8521 "%s: HddCtx validation failed", __func__);
8522 return 0;
8523 }
8524
8525 pHddCtx->isWiphySuspended = TRUE;
8526
8527 EXIT();
8528
8529 return 0;
8530}
8531
Jeff Johnson295189b2012-06-20 16:38:30 -07008532/* cfg80211_ops */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308533static struct cfg80211_ops wlan_hdd_cfg80211_ops =
Jeff Johnson295189b2012-06-20 16:38:30 -07008534{
8535 .add_virtual_intf = wlan_hdd_add_virtual_intf,
8536 .del_virtual_intf = wlan_hdd_del_virtual_intf,
8537 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
8538 .change_station = wlan_hdd_change_station,
8539#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
8540 .add_beacon = wlan_hdd_cfg80211_add_beacon,
8541 .del_beacon = wlan_hdd_cfg80211_del_beacon,
8542 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008543#else
8544 .start_ap = wlan_hdd_cfg80211_start_ap,
8545 .change_beacon = wlan_hdd_cfg80211_change_beacon,
8546 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07008547#endif
8548 .change_bss = wlan_hdd_cfg80211_change_bss,
8549 .add_key = wlan_hdd_cfg80211_add_key,
8550 .get_key = wlan_hdd_cfg80211_get_key,
8551 .del_key = wlan_hdd_cfg80211_del_key,
8552 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08008553#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07008554 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08008555#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008556 .scan = wlan_hdd_cfg80211_scan,
8557 .connect = wlan_hdd_cfg80211_connect,
8558 .disconnect = wlan_hdd_cfg80211_disconnect,
8559 .join_ibss = wlan_hdd_cfg80211_join_ibss,
8560 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
8561 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
8562 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
8563 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
Jeff Johnson295189b2012-06-20 16:38:30 -07008564 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
8565 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
8566 .mgmt_tx = wlan_hdd_action,
8567#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
8568 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
8569 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
8570 .set_txq_params = wlan_hdd_set_txq_params,
8571#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008572 .get_station = wlan_hdd_cfg80211_get_station,
8573 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
8574 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008575 .add_station = wlan_hdd_cfg80211_add_station,
8576#ifdef FEATURE_WLAN_LFR
8577 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
8578 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
8579 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
8580#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07008581#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
8582 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
8583#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008584#ifdef FEATURE_WLAN_TDLS
8585 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
8586 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
8587#endif
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308588#ifdef WLAN_FEATURE_GTK_OFFLOAD
8589 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
8590#endif /* WLAN_FEATURE_GTK_OFFLOAD */
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308591#ifdef FEATURE_WLAN_SCAN_PNO
8592 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
8593 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
8594#endif /*FEATURE_WLAN_SCAN_PNO */
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308595 .resume = wlan_hdd_cfg80211_resume_wlan,
8596 .suspend = wlan_hdd_cfg80211_suspend_wlan,
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05308597 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
Leo Chang9056f462013-08-01 19:21:11 -07008598#ifdef WLAN_NL80211_TESTMODE
8599 .testmode_cmd = wlan_hdd_cfg80211_testmode,
8600#endif
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308601 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Jeff Johnson295189b2012-06-20 16:38:30 -07008602};
8603