blob: db50abba16ae86e94881c2b1675ef901690e7c25 [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/*
534 * FUNCTION: wlan_hdd_cfg80211_init
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530535 * This function is called by hdd_wlan_startup()
536 * during initialization.
Jeff Johnson295189b2012-06-20 16:38:30 -0700537 * This function is used to initialize and register wiphy structure.
538 */
539struct wiphy *wlan_hdd_cfg80211_init(int priv_size)
540{
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 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530628int wlan_hdd_cfg80211_register(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
634 int i, j;
635
Jeff Johnsone7245742012-09-05 17:12:55 -0700636 ENTER();
637
Jeff Johnson295189b2012-06-20 16:38:30 -0700638 /* Now bind the underlying wlan device with wiphy */
639 set_wiphy_dev(wiphy, dev);
640
641 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
642
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700643 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700644
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700645#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700646 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
647 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
648 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
Jeff Johnsone7245742012-09-05 17:12:55 -0700649 | WIPHY_FLAG_OFFCHAN_TX;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700650#endif
Srinivas Girigowda640728a2013-03-28 12:21:54 -0700651#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
652 if (pCfg->isFastTransitionEnabled
James Zmuda77fb5ae2013-01-29 08:00:17 -0800653#ifdef FEATURE_WLAN_LFR
Srinivas Girigowda640728a2013-03-28 12:21:54 -0700654 || pCfg->isFastRoamIniFeatureEnabled
655#endif
656#ifdef FEATURE_WLAN_CCX
657 || pCfg->isCcxIniFeatureEnabled
658#endif
659 )
660 {
661 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
662 }
James Zmuda77fb5ae2013-01-29 08:00:17 -0800663#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800664#ifdef FEATURE_WLAN_TDLS
665 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
666 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
667#endif
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +0530668#ifdef FEATURE_WLAN_SCAN_PNO
669 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
670 wiphy->max_sched_scan_ssids = MAX_SCAN_SSID;
671 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
672#endif/*FEATURE_WLAN_SCAN_PNO*/
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800673
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700674 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
675 driver can still register regulatory callback and
676 it will get CRDA setting in wiphy->band[], but
677 driver need to determine what to do with both
678 regulatory settings */
679 wiphy->reg_notifier = wlan_hdd_crda_reg_notifier;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700680
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530681 wiphy->max_scan_ssids = MAX_SCAN_SSID;
682
Madan Mohan Koyyalamudi6815b162013-07-19 17:17:46 +0530683 wiphy->max_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Jeff Johnson295189b2012-06-20 16:38:30 -0700684
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +0530685 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
686
Jeff Johnson295189b2012-06-20 16:38:30 -0700687 /* Supports STATION & AD-HOC modes right now */
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530688 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -0700689 | BIT(NL80211_IFTYPE_ADHOC)
Jeff Johnson295189b2012-06-20 16:38:30 -0700690 | BIT(NL80211_IFTYPE_P2P_CLIENT)
691 | BIT(NL80211_IFTYPE_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -0700692 | BIT(NL80211_IFTYPE_AP);
693
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800694#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800695 if( pCfg->enableMCC )
696 {
697 /* Currently, supports up to two channels */
698 wlan_hdd_iface_combination.num_different_channels = 2;
699
700 if( !pCfg->allowMCCGODiffBI )
701 wlan_hdd_iface_combination.beacon_int_infra_match = true;
702
703 }
704 wiphy->iface_combinations = &wlan_hdd_iface_combination;
705 wiphy->n_iface_combinations = 1;
706#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800707
Jeff Johnson295189b2012-06-20 16:38:30 -0700708 /* Before registering we need to update the ht capabilitied based
709 * on ini values*/
710 if( !pCfg->ShortGI20MhzEnable )
711 {
712 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
713 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
714 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
715 }
716
717 if( !pCfg->ShortGI40MhzEnable )
718 {
719 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
720 }
721
722 if( !pCfg->nChannelBondingMode5GHz )
723 {
724 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
725 }
726
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530727 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
728 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
729
730 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
731 {
732
733 if (NULL == wiphy->bands[i])
734 {
735 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[i] is NULL, i = %d",
736 __func__, i);
737 continue;
738 }
739
740 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
741 {
742 struct ieee80211_supported_band *band = wiphy->bands[i];
743
744 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == pCfg->nBandCapability) // 5G only
745 {
746 // Enable social channels for P2P
747 if (WLAN_HDD_IS_SOCIAL_CHANNEL(band->channels[j].center_freq))
748 band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED;
749 else
750 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
751 continue;
752 }
753 else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == pCfg->nBandCapability) // 2G only
754 {
755 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
756 continue;
757 }
758 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700759 }
760 /*Initialise the supported cipher suite details*/
761 wiphy->cipher_suites = hdd_cipher_suites;
762 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
763
764 /*signal strength in mBm (100*dBm) */
765 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
766
767#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -0700768 wiphy->max_remain_on_channel_duration = 1000;
769#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700770
771 /* Register our wiphy dev with cfg80211 */
772 if (0 > wiphy_register(wiphy))
773 {
774 /* print eror */
775 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
776 return -EIO;
777 }
778
779 EXIT();
780 return 0;
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530781}
Jeff Johnson295189b2012-06-20 16:38:30 -0700782
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700783/* In this function we will try to get default country code from crda.
784 If the gCrdaDefaultCountryCode is configured in ini file,
785 we will try to call user space crda to get the regulatory settings for
786 that country. We will timeout if we can't get it from crda.
787 It's called by hdd_wlan_startup() after wlan_hdd_cfg80211_register.
788*/
789int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg)
790{
791 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Madan Mohan Koyyalamudi113ac742013-08-06 22:45:43 +0530792 int status;
793
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700794 if (memcmp(pCfg->crdaDefaultCountryCode,
795 CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) != 0)
796 {
Madan Mohan Koyyalamudi113ac742013-08-06 22:45:43 +0530797 INIT_COMPLETION(pHddCtx->driver_crda_req);
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700798 regulatory_hint(wiphy, pCfg->crdaDefaultCountryCode);
Madan Mohan Koyyalamudi113ac742013-08-06 22:45:43 +0530799 status = wait_for_completion_interruptible_timeout(
800 &pHddCtx->driver_crda_req,
801 msecs_to_jiffies(CRDA_WAIT_TIME));
802 if (!status)
803 {
804 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: timeout waiting for CRDA REQ",
805 __func__);
806 }
807
Yunsen Wange3ba1fb2013-04-05 15:04:43 -0700808 /* if the country is not found from current regulatory.bin,
809 fall back to world domain */
810 if (is_crda_regulatory_entry_valid() == VOS_FALSE)
811 crda_regulatory_entry_default(pCfg->crdaDefaultCountryCode, NUM_REG_DOMAINS-1);
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700812 }
813 return 0;
814}
815
Jeff Johnson295189b2012-06-20 16:38:30 -0700816/* In this function we will do all post VOS start initialization.
817 In this function we will register for all frame in which supplicant
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530818 is interested.
Jeff Johnson295189b2012-06-20 16:38:30 -0700819*/
820void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
821{
Jeff Johnson295189b2012-06-20 16:38:30 -0700822 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
823 /* Register for all P2P action, public action etc frames */
824 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
825
Jeff Johnsone7245742012-09-05 17:12:55 -0700826 ENTER();
827
Jeff Johnson295189b2012-06-20 16:38:30 -0700828 /* Right now we are registering these frame when driver is getting
829 initialized. Once we will move to 2.6.37 kernel, in which we have
830 frame register ops, we will move this code as a part of that */
831 /* GAS Initial Request */
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530832 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
Jeff Johnson295189b2012-06-20 16:38:30 -0700833 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
834
835 /* GAS Initial Response */
836 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
837 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530838
Jeff Johnson295189b2012-06-20 16:38:30 -0700839 /* GAS Comeback Request */
840 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
841 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
842
843 /* GAS Comeback Response */
844 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
845 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
846
847 /* P2P Public Action */
848 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530849 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
Jeff Johnson295189b2012-06-20 16:38:30 -0700850 P2P_PUBLIC_ACTION_FRAME_SIZE );
851
852 /* P2P Action */
853 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
854 (v_U8_t*)P2P_ACTION_FRAME,
855 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -0700856
Gopichand Nakkalae3d56e72013-04-21 23:33:32 +0530857 /* WNM BSS Transition Request frame */
858 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
859 (v_U8_t*)WNM_BSS_ACTION_FRAME,
860 WNM_BSS_ACTION_FRAME_SIZE );
861
Chet Lanctot186b5732013-03-18 10:26:30 -0700862#ifdef WLAN_FEATURE_11W
863 /* SA Query Response Action Frame */
864 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
865 (v_U8_t*)SA_QUERY_FRAME_RSP,
866 SA_QUERY_FRAME_RSP_SIZE );
867#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -0700868}
869
870void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
871{
Jeff Johnson295189b2012-06-20 16:38:30 -0700872 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
873 /* Register for all P2P action, public action etc frames */
874 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
875
Jeff Johnsone7245742012-09-05 17:12:55 -0700876 ENTER();
877
Jeff Johnson295189b2012-06-20 16:38:30 -0700878 /* Right now we are registering these frame when driver is getting
879 initialized. Once we will move to 2.6.37 kernel, in which we have
880 frame register ops, we will move this code as a part of that */
881 /* GAS Initial Request */
882
883 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
884 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
885
886 /* GAS Initial Response */
887 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
888 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530889
Jeff Johnson295189b2012-06-20 16:38:30 -0700890 /* GAS Comeback Request */
891 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
892 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
893
894 /* GAS Comeback Response */
895 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
896 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
897
898 /* P2P Public Action */
899 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530900 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
Jeff Johnson295189b2012-06-20 16:38:30 -0700901 P2P_PUBLIC_ACTION_FRAME_SIZE );
902
903 /* P2P Action */
904 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
905 (v_U8_t*)P2P_ACTION_FRAME,
906 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -0700907
908#ifdef WLAN_FEATURE_11W
909 /* SA Query Response Action Frame */
910 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
911 (v_U8_t*)SA_QUERY_FRAME_RSP,
912 SA_QUERY_FRAME_RSP_SIZE );
913#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -0700914}
915
916#ifdef FEATURE_WLAN_WAPI
917void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
918 const u8 *mac_addr, u8 *key , int key_Len)
919{
920 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
921 tCsrRoamSetKey setKey;
922 v_BOOL_t isConnected = TRUE;
923 int status = 0;
924 v_U32_t roamId= 0xFF;
925 tANI_U8 *pKeyPtr = NULL;
926 int n = 0;
927
928 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
929 __func__,pAdapter->device_mode);
930
Gopichand Nakkalae7480202013-02-11 15:24:22 +0530931 vos_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Jeff Johnson295189b2012-06-20 16:38:30 -0700932 setKey.keyId = key_index; // Store Key ID
933 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
934 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
935 setKey.paeRole = 0 ; // the PAE role
936 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
937 {
938 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
939 }
940 else
941 {
942 isConnected = hdd_connIsConnected(pHddStaCtx);
943 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
944 }
945 setKey.keyLength = key_Len;
946 pKeyPtr = setKey.Key;
947 memcpy( pKeyPtr, key, key_Len);
948
949 hddLog(VOS_TRACE_LEVEL_INFO,"\n%s: WAPI KEY LENGTH:0x%04x",
950 __func__, key_Len);
951 for (n = 0 ; n < key_Len; n++)
952 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
953 __func__,n,setKey.Key[n]);
954
955 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
956 if ( isConnected )
957 {
958 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
959 pAdapter->sessionId, &setKey, &roamId );
960 }
961 if ( status != 0 )
962 {
963 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
964 "[%4d] sme_RoamSetKey returned ERROR status= %d",
965 __LINE__, status );
966 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
967 }
968}
969#endif /* FEATURE_WLAN_WAPI*/
970
971#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530972int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -0700973 beacon_data_t **ppBeacon,
974 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700975#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530976int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700977 beacon_data_t **ppBeacon,
978 struct cfg80211_beacon_data *params,
979 int dtim_period)
980#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530981{
Jeff Johnson295189b2012-06-20 16:38:30 -0700982 int size;
983 beacon_data_t *beacon = NULL;
984 beacon_data_t *old = NULL;
985 int head_len,tail_len;
986
Jeff Johnsone7245742012-09-05 17:12:55 -0700987 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700988 if (params->head && !params->head_len)
989 return -EINVAL;
990
991 old = pAdapter->sessionCtx.ap.beacon;
992
993 if (!params->head && !old)
994 return -EINVAL;
995
996 if (params->tail && !params->tail_len)
997 return -EINVAL;
998
999#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
1000 /* Kernel 3.0 is not updating dtim_period for set beacon */
1001 if (!params->dtim_period)
1002 return -EINVAL;
1003#endif
1004
1005 if(params->head)
1006 head_len = params->head_len;
1007 else
1008 head_len = old->head_len;
1009
1010 if(params->tail || !old)
1011 tail_len = params->tail_len;
1012 else
1013 tail_len = old->tail_len;
1014
1015 size = sizeof(beacon_data_t) + head_len + tail_len;
1016
1017 beacon = kzalloc(size, GFP_KERNEL);
1018
1019 if( beacon == NULL )
1020 return -ENOMEM;
1021
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001022#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001023 if(params->dtim_period || !old )
1024 beacon->dtim_period = params->dtim_period;
1025 else
1026 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001027#else
1028 if(dtim_period || !old )
1029 beacon->dtim_period = dtim_period;
1030 else
1031 beacon->dtim_period = old->dtim_period;
1032#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301033
Jeff Johnson295189b2012-06-20 16:38:30 -07001034 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
1035 beacon->tail = beacon->head + head_len;
1036 beacon->head_len = head_len;
1037 beacon->tail_len = tail_len;
1038
1039 if(params->head) {
1040 memcpy (beacon->head,params->head,beacon->head_len);
1041 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301042 else {
Jeff Johnson295189b2012-06-20 16:38:30 -07001043 if(old)
1044 memcpy (beacon->head,old->head,beacon->head_len);
1045 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301046
Jeff Johnson295189b2012-06-20 16:38:30 -07001047 if(params->tail) {
1048 memcpy (beacon->tail,params->tail,beacon->tail_len);
1049 }
1050 else {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301051 if(old)
Jeff Johnson295189b2012-06-20 16:38:30 -07001052 memcpy (beacon->tail,old->tail,beacon->tail_len);
1053 }
1054
1055 *ppBeacon = beacon;
1056
1057 kfree(old);
1058
1059 return 0;
1060
1061}
Jeff Johnson295189b2012-06-20 16:38:30 -07001062
1063v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
1064{
1065 int left = length;
1066 v_U8_t *ptr = pIes;
1067 v_U8_t elem_id,elem_len;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301068
Jeff Johnson295189b2012-06-20 16:38:30 -07001069 while(left >= 2)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301070 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001071 elem_id = ptr[0];
1072 elem_len = ptr[1];
1073 left -= 2;
1074 if(elem_len > left)
1075 {
1076 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001077 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -07001078 eid,elem_len,left);
1079 return NULL;
1080 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301081 if (elem_id == eid)
Jeff Johnson295189b2012-06-20 16:38:30 -07001082 {
1083 return ptr;
1084 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301085
Jeff Johnson295189b2012-06-20 16:38:30 -07001086 left -= elem_len;
1087 ptr += (elem_len + 2);
1088 }
1089 return NULL;
1090}
1091
Jeff Johnson295189b2012-06-20 16:38:30 -07001092/* Check if rate is 11g rate or not */
1093static int wlan_hdd_rate_is_11g(u8 rate)
1094{
Sanjay Devnani28322e22013-06-21 16:13:40 -07001095 static const u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 108}; /* actual rate * 2 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001096 u8 i;
1097 for (i = 0; i < 8; i++)
1098 {
1099 if(rate == gRateArray[i])
1100 return TRUE;
1101 }
1102 return FALSE;
1103}
1104
1105/* Check for 11g rate and set proper 11g only mode */
1106static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
1107 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
1108{
1109 u8 i, num_rates = pIe[0];
1110
1111 pIe += 1;
1112 for ( i = 0; i < num_rates; i++)
1113 {
1114 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
1115 {
1116 /* If rate set have 11g rate than change the mode to 11G */
1117 *pSapHw_mode = eSAP_DOT11_MODE_11g;
1118 if (pIe[i] & BASIC_RATE_MASK)
1119 {
1120 /* If we have 11g rate as basic rate, it means mode
1121 is 11g only mode.
1122 */
1123 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
1124 *pCheckRatesfor11g = FALSE;
1125 }
1126 }
1127 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
1128 {
1129 *require_ht = TRUE;
1130 }
1131 }
1132 return;
1133}
1134
1135static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
1136{
1137 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1138 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1139 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1140 u8 checkRatesfor11g = TRUE;
1141 u8 require_ht = FALSE;
1142 u8 *pIe=NULL;
1143
1144 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
1145
1146 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
1147 pBeacon->head_len, WLAN_EID_SUPP_RATES);
1148 if (pIe != NULL)
1149 {
1150 pIe += 1;
1151 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1152 &pConfig->SapHw_mode);
1153 }
1154
1155 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1156 WLAN_EID_EXT_SUPP_RATES);
1157 if (pIe != NULL)
1158 {
1159
1160 pIe += 1;
1161 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1162 &pConfig->SapHw_mode);
1163 }
1164
1165 if( pConfig->channel > 14 )
1166 {
1167 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
1168 }
1169
1170 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1171 WLAN_EID_HT_CAPABILITY);
1172
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301173 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001174 {
1175 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
1176 if(require_ht)
1177 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
1178 }
1179}
1180
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301181static int wlan_hdd_add_ie(hdd_adapter_t* pHostapdAdapter, v_U8_t *genie,
1182 v_U8_t *total_ielen, v_U8_t *oui, v_U8_t oui_size)
1183{
1184 v_U8_t ielen = 0;
1185 v_U8_t *pIe = NULL;
1186 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1187
1188 pIe = wlan_hdd_get_vendor_oui_ie_ptr(oui, oui_size,
1189 pBeacon->tail, pBeacon->tail_len);
1190
1191 if (pIe)
1192 {
1193 ielen = pIe[1] + 2;
1194 if ((*total_ielen + ielen) <= MAX_GENIE_LEN)
1195 {
1196 vos_mem_copy(&genie[*total_ielen], pIe, ielen);
1197 }
1198 else
1199 {
1200 hddLog( VOS_TRACE_LEVEL_ERROR, "**Ie Length is too big***");
1201 return -EINVAL;
1202 }
1203 *total_ielen += ielen;
1204 }
1205 return 0;
1206}
1207
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001208#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001209static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1210 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001211#else
1212static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1213 struct cfg80211_beacon_data *params)
1214#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001215{
1216 v_U8_t *genie;
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301217 v_U8_t total_ielen = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001218 v_U8_t addIE[1] = {0};
Jeff Johnsone7245742012-09-05 17:12:55 -07001219 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001220
1221 genie = vos_mem_malloc(MAX_GENIE_LEN);
1222
1223 if(genie == NULL) {
1224
1225 return -ENOMEM;
1226 }
1227
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301228 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1229 &total_ielen, WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001230 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301231 ret = -EINVAL;
1232 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001233 }
1234
1235#ifdef WLAN_FEATURE_WFD
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301236 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1237 &total_ielen, WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE))
1238 {
1239 ret = -EINVAL;
1240 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001241 }
1242#endif
1243
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301244 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1245 &total_ielen, P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001246 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301247 ret = -EINVAL;
1248 goto done;
1249 }
1250
1251 if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode)
1252 {
1253 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1254 &total_ielen, SS_OUI_TYPE, SS_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001255 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301256 ret = -EINVAL;
1257 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001258 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001259 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001260
1261 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1262 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1263 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1264 {
1265 hddLog(LOGE,
1266 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001267 ret = -EINVAL;
1268 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001269 }
1270
1271 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1272 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1273 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1274 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1275 ==eHAL_STATUS_FAILURE)
1276 {
1277 hddLog(LOGE,
1278 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG 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 // Added for ProResp IE
1284 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1285 {
1286 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1287 u8 probe_rsp_ie_len[3] = {0};
1288 u8 counter = 0;
1289 /* Check Probe Resp Length if it is greater then 255 then Store
1290 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1291 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1292 Store More then 255 bytes into One Variable.
1293 */
1294 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1295 {
1296 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1297 {
1298 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1299 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1300 }
1301 else
1302 {
1303 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1304 rem_probe_resp_ie_len = 0;
1305 }
1306 }
1307
1308 rem_probe_resp_ie_len = 0;
1309
1310 if (probe_rsp_ie_len[0] > 0)
1311 {
1312 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1313 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1314 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1315 probe_rsp_ie_len[0], NULL,
1316 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1317 {
1318 hddLog(LOGE,
1319 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001320 ret = -EINVAL;
1321 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001322 }
1323 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1324 }
1325
1326 if (probe_rsp_ie_len[1] > 0)
1327 {
1328 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1329 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1330 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1331 probe_rsp_ie_len[1], NULL,
1332 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1333 {
1334 hddLog(LOGE,
1335 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001336 ret = -EINVAL;
1337 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001338 }
1339 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1340 }
1341
1342 if (probe_rsp_ie_len[2] > 0)
1343 {
1344 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1345 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1346 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1347 probe_rsp_ie_len[2], NULL,
1348 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1349 {
1350 hddLog(LOGE,
1351 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001352 ret = -EINVAL;
1353 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001354 }
1355 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1356 }
1357
1358 if (probe_rsp_ie_len[1] == 0 )
1359 {
1360 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1361 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1362 eANI_BOOLEAN_FALSE) )
1363 {
1364 hddLog(LOGE,
1365 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1366 }
1367 }
1368
1369 if (probe_rsp_ie_len[2] == 0 )
1370 {
1371 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1372 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1373 eANI_BOOLEAN_FALSE) )
1374 {
1375 hddLog(LOGE,
1376 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1377 }
1378 }
1379
1380 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1381 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1382 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1383 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1384 == eHAL_STATUS_FAILURE)
1385 {
1386 hddLog(LOGE,
1387 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001388 ret = -EINVAL;
1389 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001390 }
1391 }
1392 else
1393 {
1394 // Reset WNI_CFG_PROBE_RSP Flags
1395 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1396
1397 hddLog(VOS_TRACE_LEVEL_INFO,
1398 "%s: No Probe Response IE received in set beacon",
1399 __func__);
1400 }
1401
1402 // Added for AssocResp IE
1403 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1404 {
1405 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1406 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1407 params->assocresp_ies_len, NULL,
1408 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1409 {
1410 hddLog(LOGE,
1411 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001412 ret = -EINVAL;
1413 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001414 }
1415
1416 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1417 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1418 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1419 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1420 == eHAL_STATUS_FAILURE)
1421 {
1422 hddLog(LOGE,
1423 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG 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 else
1429 {
1430 hddLog(VOS_TRACE_LEVEL_INFO,
1431 "%s: No Assoc Response IE received in set beacon",
1432 __func__);
1433
1434 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1435 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1436 eANI_BOOLEAN_FALSE) )
1437 {
1438 hddLog(LOGE,
1439 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1440 }
1441 }
1442
Jeff Johnsone7245742012-09-05 17:12:55 -07001443done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001444 vos_mem_free(genie);
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301445 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07001446}
Jeff Johnson295189b2012-06-20 16:38:30 -07001447
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301448/*
Jeff Johnson295189b2012-06-20 16:38:30 -07001449 * FUNCTION: wlan_hdd_validate_operation_channel
1450 * called by wlan_hdd_cfg80211_start_bss() and
1451 * wlan_hdd_cfg80211_set_channel()
1452 * This function validates whether given channel is part of valid
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301453 * channel list.
1454 */
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001455VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001456{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301457
Jeff Johnson295189b2012-06-20 16:38:30 -07001458 v_U32_t num_ch = 0;
1459 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1460 u32 indx = 0;
1461 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301462 v_U8_t fValidChannel = FALSE, count = 0;
1463 hdd_config_t *hdd_pConfig_ini= (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301464
Jeff Johnson295189b2012-06-20 16:38:30 -07001465 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1466
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301467 if ( hdd_pConfig_ini->sapAllowAllChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001468 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301469 /* Validate the channel */
1470 for (count = RF_CHAN_1 ; count <= RF_CHAN_165 ; count++)
Jeff Johnson295189b2012-06-20 16:38:30 -07001471 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301472 if ( channel == rfChannels[count].channelNum )
1473 {
1474 fValidChannel = TRUE;
1475 break;
1476 }
1477 }
1478 if (fValidChannel != TRUE)
1479 {
1480 hddLog(VOS_TRACE_LEVEL_ERROR,
1481 "%s: Invalid Channel [%d]", __func__, channel);
1482 return VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001483 }
1484 }
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301485 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001486 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301487 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1488 valid_ch, &num_ch))
1489 {
1490 hddLog(VOS_TRACE_LEVEL_ERROR,
1491 "%s: failed to get valid channel list", __func__);
1492 return VOS_STATUS_E_FAILURE;
1493 }
1494 for (indx = 0; indx < num_ch; indx++)
1495 {
1496 if (channel == valid_ch[indx])
1497 {
1498 break;
1499 }
1500 }
1501
1502 if (indx >= num_ch)
1503 {
1504 hddLog(VOS_TRACE_LEVEL_ERROR,
1505 "%s: Invalid Channel [%d]", __func__, channel);
1506 return VOS_STATUS_E_FAILURE;
1507 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001508 }
1509 return VOS_STATUS_SUCCESS;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301510
Jeff Johnson295189b2012-06-20 16:38:30 -07001511}
1512
Viral Modi3a32cc52013-02-08 11:14:52 -08001513/**
1514 * FUNCTION: wlan_hdd_cfg80211_set_channel
1515 * This function is used to set the channel number
1516 */
1517static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
1518 struct ieee80211_channel *chan,
1519 enum nl80211_channel_type channel_type
1520 )
1521{
1522 v_U32_t num_ch = 0;
Jeff Johnson4416a782013-03-25 14:17:50 -07001523 int channel = 0;
Viral Modi3a32cc52013-02-08 11:14:52 -08001524 hdd_adapter_t *pAdapter = NULL;
1525 int freq = chan->center_freq; /* freq is in MHZ */
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301526 hdd_context_t *pHddCtx;
1527 int status;
Viral Modi3a32cc52013-02-08 11:14:52 -08001528
1529 ENTER();
1530
1531 if( NULL == dev )
1532 {
1533 hddLog(VOS_TRACE_LEVEL_ERROR,
1534 "%s: Called with dev = NULL.\n", __func__);
1535 return -ENODEV;
1536 }
1537 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1538
1539 hddLog(VOS_TRACE_LEVEL_INFO,
1540 "%s: device_mode = %d freq = %d \n",__func__,
1541 pAdapter->device_mode, chan->center_freq);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301542
1543 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1544 status = wlan_hdd_validate_context(pHddCtx);
1545
1546 if (0 != status)
Viral Modi3a32cc52013-02-08 11:14:52 -08001547 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301548 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1549 "%s: HDD context is not valid", __func__);
1550 return status;
Viral Modi3a32cc52013-02-08 11:14:52 -08001551 }
1552
1553 /*
1554 * Do freq to chan conversion
1555 * TODO: for 11a
1556 */
1557
1558 channel = ieee80211_frequency_to_channel(freq);
1559
1560 /* Check freq range */
1561 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
1562 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
1563 {
1564 hddLog(VOS_TRACE_LEVEL_ERROR,
1565 "%s: Channel [%d] is outside valid range from %d to %d\n",
1566 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
1567 WNI_CFG_CURRENT_CHANNEL_STAMAX);
1568 return -EINVAL;
1569 }
1570
1571 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1572
Gopichand Nakkala6ab19562013-03-07 13:59:42 +05301573 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode) &&
1574 (WLAN_HDD_P2P_GO != pAdapter->device_mode))
Viral Modi3a32cc52013-02-08 11:14:52 -08001575 {
1576 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
1577 {
1578 hddLog(VOS_TRACE_LEVEL_ERROR,
1579 "%s: Invalid Channel [%d] \n", __func__, channel);
1580 return -EINVAL;
1581 }
1582 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1583 "%s: set channel to [%d] for device mode =%d",
1584 __func__, channel,pAdapter->device_mode);
1585 }
1586 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Viral Modi3a32cc52013-02-08 11:14:52 -08001587 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Viral Modi3a32cc52013-02-08 11:14:52 -08001588 )
1589 {
1590 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
1591 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
1592 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1593
1594 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
1595 {
1596 /* Link is up then return cant set channel*/
1597 hddLog( VOS_TRACE_LEVEL_ERROR,
1598 "%s: IBSS Associated, can't set the channel\n", __func__);
1599 return -EINVAL;
1600 }
1601
1602 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
1603 pHddStaCtx->conn_info.operationChannel = channel;
1604 pRoamProfile->ChannelInfo.ChannelList =
1605 &pHddStaCtx->conn_info.operationChannel;
1606 }
1607 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Viral Modi3a32cc52013-02-08 11:14:52 -08001608 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Viral Modi3a32cc52013-02-08 11:14:52 -08001609 )
1610 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301611 if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
1612 {
1613 if(VOS_STATUS_SUCCESS !=
1614 wlan_hdd_validate_operation_channel(pAdapter,channel))
1615 {
1616 hddLog(VOS_TRACE_LEVEL_ERROR,
1617 "%s: Invalid Channel [%d] \n", __func__, channel);
1618 return -EINVAL;
1619 }
1620 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1621 }
1622 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
Viral Modi3a32cc52013-02-08 11:14:52 -08001623 {
1624 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
1625
1626 /* If auto channel selection is configured as enable/ 1 then ignore
1627 channel set by supplicant
1628 */
1629 if ( cfg_param->apAutoChannelSelection )
1630 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301631 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel =
1632 AUTO_CHANNEL_SELECT;
Viral Modi3a32cc52013-02-08 11:14:52 -08001633 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1634 "%s: set channel to auto channel (0) for device mode =%d",
1635 __func__, pAdapter->device_mode);
1636 }
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301637 else
1638 {
1639 if(VOS_STATUS_SUCCESS !=
1640 wlan_hdd_validate_operation_channel(pAdapter,channel))
1641 {
1642 hddLog(VOS_TRACE_LEVEL_ERROR,
1643 "%s: Invalid Channel [%d] \n", __func__, channel);
1644 return -EINVAL;
1645 }
1646 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1647 }
Viral Modi3a32cc52013-02-08 11:14:52 -08001648 }
1649 }
1650 else
1651 {
1652 hddLog(VOS_TRACE_LEVEL_FATAL,
1653 "%s: Invalid device mode failed to set valid channel", __func__);
1654 return -EINVAL;
1655 }
1656 EXIT();
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301657 return status;
Viral Modi3a32cc52013-02-08 11:14:52 -08001658}
1659
Jeff Johnson295189b2012-06-20 16:38:30 -07001660#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1661static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1662 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001663#else
1664static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1665 struct cfg80211_beacon_data *params,
1666 const u8 *ssid, size_t ssid_len,
1667 enum nl80211_hidden_ssid hidden_ssid)
1668#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001669{
1670 tsap_Config_t *pConfig;
1671 beacon_data_t *pBeacon = NULL;
1672 struct ieee80211_mgmt *pMgmt_frame;
1673 v_U8_t *pIe=NULL;
1674 v_U16_t capab_info;
1675 eCsrAuthType RSNAuthType;
1676 eCsrEncryptionType RSNEncryptType;
1677 eCsrEncryptionType mcRSNEncryptType;
1678 int status = VOS_STATUS_SUCCESS;
1679 tpWLAN_SAPEventCB pSapEventCallback;
1680 hdd_hostapd_state_t *pHostapdState;
1681 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1682 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301683 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001684 struct qc_mac_acl_entry *acl_entry = NULL;
1685 v_SINT_t i;
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001686 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001687
1688 ENTER();
1689
1690 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1691
1692 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1693
1694 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1695
1696 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1697
1698 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1699
1700 //channel is already set in the set_channel Call back
1701 //pConfig->channel = pCommitConfig->channel;
1702
1703 /*Protection parameter to enable or disable*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301704 pConfig->protEnabled =
Jeff Johnson295189b2012-06-20 16:38:30 -07001705 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1706
1707 pConfig->dtim_period = pBeacon->dtim_period;
1708
1709 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1710 pConfig->dtim_period);
1711
1712
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001713 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001714 {
1715 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001716 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001717 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001718 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001719 tANI_BOOLEAN restartNeeded;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001720 pConfig->ieee80211d = 1;
1721 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1722 sme_setRegInfo(hHal, pConfig->countryCode);
1723 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
Jeff Johnson295189b2012-06-20 16:38:30 -07001724 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001725 else
1726 {
1727 pConfig->ieee80211d = 0;
1728 }
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301729 /*
1730 * If auto channel is configured i.e. channel is 0,
1731 * so skip channel validation.
1732 */
1733 if( AUTO_CHANNEL_SELECT != pConfig->channel )
1734 {
1735 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1736 {
1737 hddLog(VOS_TRACE_LEVEL_ERROR,
1738 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1739 return -EINVAL;
1740 }
1741 }
1742 else
1743 {
1744 if(1 != pHddCtx->is_dynamic_channel_range_set)
1745 {
1746 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
1747 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
1748 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
1749 }
1750 pHddCtx->is_dynamic_channel_range_set = 0;
1751 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001752 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001753 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001754 {
1755 pConfig->ieee80211d = 0;
1756 }
1757 pConfig->authType = eSAP_AUTO_SWITCH;
1758
1759 capab_info = pMgmt_frame->u.beacon.capab_info;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301760
1761 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
Jeff Johnson295189b2012-06-20 16:38:30 -07001762 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1763
1764 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1765
1766 /*Set wps station to configured*/
1767 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1768
1769 if(pIe)
1770 {
1771 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1772 {
1773 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1774 return -EINVAL;
1775 }
1776 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1777 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001778 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001779 /* Check 15 bit of WPS IE as it contain information for wps state
1780 * WPS state
1781 */
1782 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1783 {
1784 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1785 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1786 {
1787 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1788 }
1789 }
1790 }
1791 else
1792 {
1793 pConfig->wps_state = SAP_WPS_DISABLED;
1794 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301795 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
Jeff Johnson295189b2012-06-20 16:38:30 -07001796
1797 pConfig->RSNWPAReqIELength = 0;
1798 pConfig->pRSNWPAReqIE = NULL;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301799 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001800 WLAN_EID_RSN);
1801 if(pIe && pIe[1])
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301802 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001803 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1804 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1805 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301806 /* The actual processing may eventually be more extensive than
1807 * this. Right now, just consume any PMKIDs that are sent in
Jeff Johnson295189b2012-06-20 16:38:30 -07001808 * by the app.
1809 * */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301810 status = hdd_softap_unpackIE(
Jeff Johnson295189b2012-06-20 16:38:30 -07001811 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1812 &RSNEncryptType,
1813 &mcRSNEncryptType,
1814 &RSNAuthType,
1815 pConfig->pRSNWPAReqIE[1]+2,
1816 pConfig->pRSNWPAReqIE );
1817
1818 if( VOS_STATUS_SUCCESS == status )
1819 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301820 /* Now copy over all the security attributes you have
1821 * parsed out
Jeff Johnson295189b2012-06-20 16:38:30 -07001822 * */
1823 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1824 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1825 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1826 = RSNEncryptType;
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05301827 hddLog( LOG1, FL("CSR AuthType = %d, "
Jeff Johnson295189b2012-06-20 16:38:30 -07001828 "EncryptionType = %d mcEncryptionType = %d\n"),
1829 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1830 }
1831 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301832
Jeff Johnson295189b2012-06-20 16:38:30 -07001833 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1834 pBeacon->tail, pBeacon->tail_len);
1835
1836 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1837 {
1838 if (pConfig->pRSNWPAReqIE)
1839 {
1840 /*Mixed mode WPA/WPA2*/
1841 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1842 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1843 }
1844 else
1845 {
1846 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1847 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1848 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301849 status = hdd_softap_unpackIE(
Jeff Johnson295189b2012-06-20 16:38:30 -07001850 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1851 &RSNEncryptType,
1852 &mcRSNEncryptType,
1853 &RSNAuthType,
1854 pConfig->pRSNWPAReqIE[1]+2,
1855 pConfig->pRSNWPAReqIE );
1856
1857 if( VOS_STATUS_SUCCESS == status )
1858 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301859 /* Now copy over all the security attributes you have
1860 * parsed out
Jeff Johnson295189b2012-06-20 16:38:30 -07001861 * */
1862 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1863 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1864 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1865 = RSNEncryptType;
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05301866 hddLog( LOG1, FL("CSR AuthType = %d, "
Jeff Johnson295189b2012-06-20 16:38:30 -07001867 "EncryptionType = %d mcEncryptionType = %d\n"),
1868 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1869 }
1870 }
1871 }
1872
Jeff Johnson4416a782013-03-25 14:17:50 -07001873 if (pConfig->RSNWPAReqIELength > sizeof wpaRsnIEdata) {
1874 hddLog( VOS_TRACE_LEVEL_ERROR, "**RSNWPAReqIELength is too large***");
1875 return -EINVAL;
1876 }
1877
Jeff Johnson295189b2012-06-20 16:38:30 -07001878 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1879
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001880#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001881 if (params->ssid != NULL)
1882 {
1883 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1884 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1885 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1886 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1887 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001888#else
1889 if (ssid != NULL)
1890 {
1891 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1892 pConfig->SSIDinfo.ssid.length = ssid_len;
1893 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1894 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1895 }
1896#endif
1897
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301898 vos_mem_copy(pConfig->self_macaddr.bytes,
Jeff Johnson295189b2012-06-20 16:38:30 -07001899 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301900
Jeff Johnson295189b2012-06-20 16:38:30 -07001901 /* default value */
1902 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1903 pConfig->num_accept_mac = 0;
1904 pConfig->num_deny_mac = 0;
1905
1906 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1907 pBeacon->tail, pBeacon->tail_len);
1908
1909 /* pIe for black list is following form:
1910 type : 1 byte
1911 length : 1 byte
1912 OUI : 4 bytes
1913 acl type : 1 byte
1914 no of mac addr in black list: 1 byte
1915 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301916 */
1917 if ((pIe != NULL) && (pIe[1] != 0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001918 {
1919 pConfig->SapMacaddr_acl = pIe[6];
1920 pConfig->num_deny_mac = pIe[7];
1921 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1922 pIe[6], pIe[7]);
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05301923 if (pConfig->num_deny_mac > MAX_ACL_MAC_ADDRESS)
1924 pConfig->num_deny_mac = MAX_ACL_MAC_ADDRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07001925 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1926 for (i = 0; i < pConfig->num_deny_mac; i++)
1927 {
1928 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1929 acl_entry++;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301930 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001931 }
1932 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1933 pBeacon->tail, pBeacon->tail_len);
1934
1935 /* pIe for white list is following form:
1936 type : 1 byte
1937 length : 1 byte
1938 OUI : 4 bytes
1939 acl type : 1 byte
1940 no of mac addr in white list: 1 byte
1941 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301942 */
1943 if ((pIe != NULL) && (pIe[1] != 0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001944 {
1945 pConfig->SapMacaddr_acl = pIe[6];
1946 pConfig->num_accept_mac = pIe[7];
1947 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
1948 pIe[6], pIe[7]);
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05301949 if (pConfig->num_accept_mac > MAX_ACL_MAC_ADDRESS)
1950 pConfig->num_accept_mac = MAX_ACL_MAC_ADDRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07001951 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1952 for (i = 0; i < pConfig->num_accept_mac; i++)
1953 {
1954 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1955 acl_entry++;
1956 }
1957 }
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05301958
Jeff Johnson295189b2012-06-20 16:38:30 -07001959 wlan_hdd_set_sapHwmode(pHostapdAdapter);
1960
Jeff Johnsone7245742012-09-05 17:12:55 -07001961#ifdef WLAN_FEATURE_11AC
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08001962 /* Overwrite the hostapd setting for HW mode only for 11ac.
1963 * This is valid only if mode is set to 11n in hostapd and either AUTO or 11ac in .ini .
1964 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode) */
1965 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
1966 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301967 (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08001968 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1969 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07001970 {
1971 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
Ravi Joshi83bfaa12013-05-28 22:12:08 -07001972
1973 /* Disable VHT support in 2.4 GHz band */
1974 if (pConfig->channel <= 14 &&
1975 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->enableVhtFor24GHzBand == FALSE)
1976 {
1977 pConfig->SapHw_mode = eSAP_DOT11_MODE_11n;
1978 }
Jeff Johnsone7245742012-09-05 17:12:55 -07001979 }
1980#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301981
Ravi Joshiaeb7d9e2013-05-02 12:28:14 -07001982 if ( AUTO_CHANNEL_SELECT != pConfig->channel )
1983 {
1984 sme_SelectCBMode(hHal,
1985 sapConvertSapPhyModeToCsrPhyMode(pConfig->SapHw_mode),
1986 pConfig->channel);
1987 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001988 // ht_capab is not what the name conveys,this is used for protection bitmap
1989 pConfig->ht_capab =
1990 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
1991
1992 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
1993 {
1994 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
1995 return -EINVAL;
1996 }
1997
1998 //Uapsd Enabled Bit
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301999 pConfig->UapsdEnable =
Jeff Johnson295189b2012-06-20 16:38:30 -07002000 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
2001 //Enable OBSS protection
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302002 pConfig->obssProtEnabled =
2003 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
Jeff Johnson295189b2012-06-20 16:38:30 -07002004
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302005 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
Jeff Johnson295189b2012-06-20 16:38:30 -07002006 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302007 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
Jeff Johnson295189b2012-06-20 16:38:30 -07002008 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
2009 (int)pConfig->channel);
2010 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302011 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
2012 pConfig->authType);
Jeff Johnson295189b2012-06-20 16:38:30 -07002013 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302014 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
Jeff Johnson295189b2012-06-20 16:38:30 -07002015 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
2016 pConfig->protEnabled, pConfig->obssProtEnabled);
2017
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302018 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07002019 {
2020 //Bss already started. just return.
2021 //TODO Probably it should update some beacon params.
2022 hddLog( LOGE, "Bss Already started...Ignore the request");
2023 EXIT();
2024 return 0;
2025 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302026
Jeff Johnson295189b2012-06-20 16:38:30 -07002027 pConfig->persona = pHostapdAdapter->device_mode;
2028
2029 pSapEventCallback = hdd_hostapd_SAPEventCB;
2030 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
2031 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
2032 {
2033 hddLog(LOGE,FL("SAP Start Bss fail\n"));
2034 return -EINVAL;
2035 }
2036
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302037 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07002038 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
2039
2040 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302041
Jeff Johnson295189b2012-06-20 16:38:30 -07002042 if (!VOS_IS_STATUS_SUCCESS(status))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302043 {
2044 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07002045 ("ERROR: HDD vos wait for single_event failed!!\n"));
2046 VOS_ASSERT(0);
2047 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302048
Jeff Johnson295189b2012-06-20 16:38:30 -07002049 //Succesfully started Bss update the state bit.
2050 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
2051
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002052#ifdef WLAN_FEATURE_P2P_DEBUG
2053 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
2054 {
2055 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
2056 {
2057 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
2058 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002059 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002060 }
2061 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
2062 {
2063 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
2064 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002065 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002066 }
2067 }
2068#endif
2069
Jeff Johnson295189b2012-06-20 16:38:30 -07002070 pHostapdState->bCommit = TRUE;
2071 EXIT();
2072
2073 return 0;
2074}
2075
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002076#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302077static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
2078 struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -07002079 struct beacon_parameters *params)
2080{
2081 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302082 hdd_context_t *pHddCtx;
2083 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002084
2085 ENTER();
2086
2087 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
2088
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302089 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2090 status = wlan_hdd_validate_context(pHddCtx);
2091
2092 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002093 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302094 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2095 "%s: HDD context is not valid", __func__);
2096 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002097 }
2098
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302099 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002100 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002101 )
2102 {
2103 beacon_data_t *old,*new;
2104
2105 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302106
Jeff Johnson295189b2012-06-20 16:38:30 -07002107 if (old)
2108 return -EALREADY;
2109
2110 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2111
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302112 if(status != VOS_STATUS_SUCCESS)
Jeff Johnson295189b2012-06-20 16:38:30 -07002113 {
2114 hddLog(VOS_TRACE_LEVEL_FATAL,
2115 "%s:Error!!! Allocating the new beacon\n",__func__);
2116 return -EINVAL;
2117 }
2118
2119 pAdapter->sessionCtx.ap.beacon = new;
2120
2121 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2122 }
2123
2124 EXIT();
2125 return status;
2126}
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302127
2128static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07002129 struct net_device *dev,
2130 struct beacon_parameters *params)
2131{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302132 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302133 hdd_context_t *pHddCtx;
2134 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002135
2136 ENTER();
2137
2138 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2139 __func__,pAdapter->device_mode);
2140
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302141 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2142 status = wlan_hdd_validate_context(pHddCtx);
2143
2144 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002145 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302146 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2147 "%s: HDD context is not valid", __func__);
2148 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002149 }
2150
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302151 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002152 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302153 )
Jeff Johnson295189b2012-06-20 16:38:30 -07002154 {
2155 beacon_data_t *old,*new;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302156
Jeff Johnson295189b2012-06-20 16:38:30 -07002157 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302158
Jeff Johnson295189b2012-06-20 16:38:30 -07002159 if (!old)
2160 return -ENOENT;
2161
2162 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2163
2164 if(status != VOS_STATUS_SUCCESS) {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302165 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -07002166 "%s: Error!!! Allocating the new beacon\n",__func__);
2167 return -EINVAL;
2168 }
2169
2170 pAdapter->sessionCtx.ap.beacon = new;
2171
2172 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2173 }
2174
2175 EXIT();
2176 return status;
2177}
2178
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002179#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
2180
2181#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002182static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
2183 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002184#else
2185static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
2186 struct net_device *dev)
2187#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002188{
2189 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07002190 hdd_context_t *pHddCtx = NULL;
2191 hdd_scaninfo_t *pScanInfo = NULL;
2192 hdd_adapter_t *staAdapter = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302193 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002194
2195 ENTER();
2196
2197 if (NULL == pAdapter)
2198 {
2199 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002200 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002201 return -ENODEV;
2202 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002203
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302204 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2205 status = wlan_hdd_validate_context(pHddCtx);
2206
2207 if (0 != status)
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002208 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302209 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2210 "%s: HDD context is not valid", __func__);
2211 return status;
Jeff Johnson4416a782013-03-25 14:17:50 -07002212 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002213
2214 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
2215 if (NULL == staAdapter)
2216 {
2217 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
2218 if (NULL == staAdapter)
2219 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302220 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002221 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002222 return -ENODEV;
2223 }
2224 }
2225
2226 pScanInfo = &pHddCtx->scan_info;
2227
Jeff Johnson295189b2012-06-20 16:38:30 -07002228 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2229 __func__,pAdapter->device_mode);
2230
Jeff Johnsone7245742012-09-05 17:12:55 -07002231 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
2232 {
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002233 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Jeff Johnsone7245742012-09-05 17:12:55 -07002234 hdd_abort_mac_scan(staAdapter->pHddCtx);
2235 status = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002236 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07002237 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
2238 if (!status)
2239 {
2240 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson902c9832012-12-10 14:28:09 -08002241 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002242 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07002243 VOS_ASSERT(pScanInfo->mScanPending);
2244 return 0;
2245 }
2246 }
2247
Jeff Johnson295189b2012-06-20 16:38:30 -07002248 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002249 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002250 )
2251 {
2252 beacon_data_t *old;
2253
2254 old = pAdapter->sessionCtx.ap.beacon;
2255
2256 if (!old)
2257 return -ENOENT;
2258
Jeff Johnson295189b2012-06-20 16:38:30 -07002259 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002260
2261 mutex_lock(&pHddCtx->sap_lock);
2262 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2263 {
Jeff Johnson4416a782013-03-25 14:17:50 -07002264 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss(pHddCtx->pvosContext) ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07002265 {
2266 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2267
2268 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2269
2270 if (!VOS_IS_STATUS_SUCCESS(status))
2271 {
2272 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2273 ("ERROR: HDD vos wait for single_event failed!!\n"));
2274 VOS_ASSERT(0);
2275 }
2276 }
2277 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2278 }
2279 mutex_unlock(&pHddCtx->sap_lock);
2280
2281 if(status != VOS_STATUS_SUCCESS)
2282 {
2283 hddLog(VOS_TRACE_LEVEL_FATAL,
2284 "%s:Error!!! Stopping the BSS\n",__func__);
2285 return -EINVAL;
2286 }
2287
Jeff Johnson4416a782013-03-25 14:17:50 -07002288 if (ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002289 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
2290 ==eHAL_STATUS_FAILURE)
2291 {
2292 hddLog(LOGE,
2293 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
2294 }
2295
Jeff Johnson4416a782013-03-25 14:17:50 -07002296 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002297 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2298 eANI_BOOLEAN_FALSE) )
2299 {
2300 hddLog(LOGE,
2301 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
2302 }
2303
2304 // Reset WNI_CFG_PROBE_RSP Flags
2305 wlan_hdd_reset_prob_rspies(pAdapter);
2306
2307 pAdapter->sessionCtx.ap.beacon = NULL;
2308 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002309#ifdef WLAN_FEATURE_P2P_DEBUG
2310 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
2311 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
2312 {
2313 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
2314 "GO got removed");
2315 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
2316 }
2317#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002318 }
2319 EXIT();
2320 return status;
2321}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002322
2323#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2324
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302325static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2326 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002327 struct cfg80211_ap_settings *params)
2328{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302329 hdd_adapter_t *pAdapter;
2330 hdd_context_t *pHddCtx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302331 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002332
2333 ENTER();
2334
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302335 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002336 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302337 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302338 "%s: Device is Null", __func__);
2339 return -ENODEV;
2340 }
2341
2342 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2343 if (NULL == pAdapter)
2344 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302345 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302346 "%s: HDD adapter is Null", __func__);
2347 return -ENODEV;
2348 }
2349
2350 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2351 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302352 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302353 "%s: HDD adapter magic is invalid", __func__);
2354 return -ENODEV;
2355 }
2356
2357 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302358 status = wlan_hdd_validate_context(pHddCtx);
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302359
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302360 if (0 != status)
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302361 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302362 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2363 "%s: HDD context is not valid", __func__);
2364 return status;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302365 }
2366
2367 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2368 __func__, pAdapter->device_mode);
2369
2370 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002371 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002372 )
2373 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302374 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002375
2376 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302377
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002378 if (old)
2379 return -EALREADY;
2380
2381 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2382
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302383 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002384 {
2385 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302386 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002387 return -EINVAL;
2388 }
2389 pAdapter->sessionCtx.ap.beacon = new;
Viral Modi3a32cc52013-02-08 11:14:52 -08002390#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Yue Maf49ba872013-08-19 12:04:25 -07002391 wlan_hdd_cfg80211_set_channel(wiphy, dev,
2392#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2393 params->channel, params->channel_type);
2394#else
2395 params->chandef.chan, cfg80211_get_chandef_type(&(params->chandef)));
2396#endif
Viral Modi3a32cc52013-02-08 11:14:52 -08002397#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002398 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2399 params->ssid_len, params->hidden_ssid);
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05302400 if (0 == status)
2401 {
2402 hdd_start_p2p_go_connection_in_progress_timer(pAdapter);
2403 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002404 }
2405
2406 EXIT();
2407 return status;
2408}
2409
2410
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302411static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002412 struct net_device *dev,
2413 struct cfg80211_beacon_data *params)
2414{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302415 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302416 hdd_context_t *pHddCtx;
2417 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002418
2419 ENTER();
2420
2421 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2422 __func__, pAdapter->device_mode);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302423
2424 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2425 status = wlan_hdd_validate_context(pHddCtx);
2426
2427 if (0 != status)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002428 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302429 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2430 "%s: HDD context is not valid", __func__);
2431 return status;
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002432 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002433
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302434 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002435 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302436 )
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002437 {
2438 beacon_data_t *old,*new;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302439
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002440 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302441
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002442 if (!old)
2443 return -ENOENT;
2444
2445 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2446
2447 if(status != VOS_STATUS_SUCCESS) {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302448 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002449 "%s: Error!!! Allocating the new beacon\n",__func__);
2450 return -EINVAL;
2451 }
2452
2453 pAdapter->sessionCtx.ap.beacon = new;
2454
2455 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2456 }
2457
2458 EXIT();
2459 return status;
2460}
2461
2462#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2463
Jeff Johnson295189b2012-06-20 16:38:30 -07002464
2465static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2466 struct net_device *dev,
2467 struct bss_parameters *params)
2468{
2469 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2470
2471 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302472
Jeff Johnson295189b2012-06-20 16:38:30 -07002473 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2474 __func__,pAdapter->device_mode);
2475
2476 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002477 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302478 )
Jeff Johnson295189b2012-06-20 16:38:30 -07002479 {
2480 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2481 * want to update this parameter */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302482 if (-1 != params->ap_isolate)
Jeff Johnson295189b2012-06-20 16:38:30 -07002483 {
2484 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302485 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002486 }
2487
2488 EXIT();
2489 return 0;
2490}
2491
2492/*
2493 * FUNCTION: wlan_hdd_cfg80211_change_iface
2494 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2495 */
2496int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2497 struct net_device *ndev,
2498 enum nl80211_iftype type,
2499 u32 *flags,
2500 struct vif_params *params
2501 )
2502{
2503 struct wireless_dev *wdev;
2504 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2505 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002506 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002507 tCsrRoamProfile *pRoamProfile = NULL;
2508 eCsrRoamBssType LastBSSType;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302509 hdd_config_t *pConfig = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002510 eMib_dot11DesiredBssType connectedBssType;
2511 VOS_STATUS status;
2512
2513 ENTER();
2514
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302515 status = wlan_hdd_validate_context(pHddCtx);
2516
2517 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07002518 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302519 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2520 "%s: HDD context is not valid", __func__);
2521 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002522 }
2523
2524 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2525 __func__, pAdapter->device_mode);
2526
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302527 pConfig = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07002528 wdev = ndev->ieee80211_ptr;
2529
2530#ifdef WLAN_BTAMP_FEATURE
2531 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2532 (NL80211_IFTYPE_ADHOC == type)||
2533 (NL80211_IFTYPE_AP == type)||
2534 (NL80211_IFTYPE_P2P_GO == type))
2535 {
2536 pHddCtx->isAmpAllowed = VOS_FALSE;
2537 // stop AMP traffic
2538 status = WLANBAP_StopAmp();
2539 if(VOS_STATUS_SUCCESS != status )
2540 {
2541 pHddCtx->isAmpAllowed = VOS_TRUE;
2542 hddLog(VOS_TRACE_LEVEL_FATAL,
2543 "%s: Failed to stop AMP", __func__);
2544 return -EINVAL;
2545 }
2546 }
2547#endif //WLAN_BTAMP_FEATURE
2548 /* Reset the current device mode bit mask*/
2549 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2550
2551 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07002552 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002553 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002554 )
2555 {
2556 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2557 pRoamProfile = &pWextState->roamProfile;
2558 LastBSSType = pRoamProfile->BSSType;
2559
2560 switch (type)
2561 {
2562 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002563 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002564 hddLog(VOS_TRACE_LEVEL_INFO,
2565 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2566 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002567#ifdef WLAN_FEATURE_11AC
2568 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2569 {
2570 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2571 }
2572#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302573 pRoamProfile->phyMode =
Jeff Johnsone7245742012-09-05 17:12:55 -07002574 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002575 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002576 //Check for sub-string p2p to confirm its a p2p interface
2577 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302578 {
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002579 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2580 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2581 }
2582 else
2583 {
2584 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002585 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002586 }
Madan Mohan Koyyalamudi81746922013-07-17 14:38:51 +05302587#ifdef FEATURE_WLAN_TDLS
2588 /* The open adapter for the p2p shall skip initializations in
2589 * tdls_init if the device mode is WLAN_HDD_P2P_DEVICE, for
2590 * TDLS is supported only on WLAN_HDD_P2P_CLIENT. Hence invoke
2591 * tdls_init when the change_iface sets the device mode to
2592 * WLAN_HDD_P2P_CLIENT.
2593 */
2594
2595 if ( pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2596 {
2597 if (0 != wlan_hdd_tdls_init (pAdapter))
2598 {
2599 return -EINVAL;
2600 }
2601 }
2602#endif
2603
Jeff Johnson295189b2012-06-20 16:38:30 -07002604 break;
2605 case NL80211_IFTYPE_ADHOC:
2606 hddLog(VOS_TRACE_LEVEL_INFO,
2607 "%s: setting interface Type to ADHOC", __func__);
2608 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2609 pRoamProfile->phyMode =
2610 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Shailender Karmuchia734f332013-04-19 14:02:48 -07002611 pAdapter->device_mode = WLAN_HDD_IBSS;
Jeff Johnson295189b2012-06-20 16:38:30 -07002612 wdev->iftype = type;
2613 break;
2614
2615 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002616 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002617 {
2618 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2619 "%s: setting interface Type to %s", __func__,
2620 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2621
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002622 //Cancel any remain on channel for GO mode
2623 if (NL80211_IFTYPE_P2P_GO == type)
2624 {
2625 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2626 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002627 if (NL80211_IFTYPE_AP == type)
2628 {
2629 /* As Loading WLAN Driver one interface being created for p2p device
2630 * address. This will take one HW STA and the max number of clients
2631 * that can connect to softAP will be reduced by one. so while changing
2632 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2633 * interface as it is not required in SoftAP mode.
2634 */
2635
2636 // Get P2P Adapter
2637 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2638
2639 if (pP2pAdapter)
2640 {
2641 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2642 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2643 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2644 }
2645 }
2646
Jeff Johnson295189b2012-06-20 16:38:30 -07002647 //De-init the adapter.
2648 hdd_stop_adapter( pHddCtx, pAdapter );
2649 hdd_deinit_adapter( pHddCtx, pAdapter );
2650 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
Jeff Johnson295189b2012-06-20 16:38:30 -07002651 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2652 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002653
2654 //Disable BMPS and IMPS if enabled
2655 //before starting Go
2656 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2657 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302658 if(VOS_STATUS_E_FAILURE ==
Jeff Johnson32d95a32012-09-10 13:15:23 -07002659 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2660 {
2661 //Fail to Exit BMPS
2662 VOS_ASSERT(0);
2663 }
2664 }
2665
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002666 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2667 (pConfig->apRandomBssidEnabled))
2668 {
2669 /* To meet Android requirements create a randomized
2670 MAC address of the form 02:1A:11:Fx:xx:xx */
2671 get_random_bytes(&ndev->dev_addr[3], 3);
2672 ndev->dev_addr[0] = 0x02;
2673 ndev->dev_addr[1] = 0x1A;
2674 ndev->dev_addr[2] = 0x11;
2675 ndev->dev_addr[3] |= 0xF0;
2676 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2677 VOS_MAC_ADDR_SIZE);
2678 pr_info("wlan: Generated HotSpot BSSID "
2679 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2680 ndev->dev_addr[0],
2681 ndev->dev_addr[1],
2682 ndev->dev_addr[2],
2683 ndev->dev_addr[3],
2684 ndev->dev_addr[4],
2685 ndev->dev_addr[5]);
2686 }
2687
Jeff Johnson295189b2012-06-20 16:38:30 -07002688 hdd_set_ap_ops( pAdapter->dev );
2689
2690 status = hdd_init_ap_mode(pAdapter);
2691 if(status != VOS_STATUS_SUCCESS)
2692 {
2693 hddLog(VOS_TRACE_LEVEL_FATAL,
2694 "%s: Error initializing the ap mode", __func__);
2695 return -EINVAL;
2696 }
2697 hdd_set_conparam(1);
2698
Jeff Johnson295189b2012-06-20 16:38:30 -07002699 /*interface type changed update in wiphy structure*/
2700 if(wdev)
2701 {
2702 wdev->iftype = type;
2703 pHddCtx->change_iface = type;
2704 }
2705 else
2706 {
2707 hddLog(VOS_TRACE_LEVEL_ERROR,
2708 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2709 return -EINVAL;
2710 }
2711 goto done;
2712 }
2713
2714 default:
2715 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2716 __func__);
2717 return -EOPNOTSUPP;
2718 }
2719 }
2720 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002721 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002722 )
2723 {
2724 switch(type)
2725 {
2726 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002727 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002728 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002729 hdd_stop_adapter( pHddCtx, pAdapter );
2730 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002731 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002732 //Check for sub-string p2p to confirm its a p2p interface
2733 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002734 {
2735 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2736 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2737 }
2738 else
2739 {
2740 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002741 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002742 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002743 hdd_set_conparam(0);
2744 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002745 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2746 hdd_set_station_ops( pAdapter->dev );
2747 status = hdd_init_station_mode( pAdapter );
2748 if( VOS_STATUS_SUCCESS != status )
2749 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002750 /* In case of JB, for P2P-GO, only change interface will be called,
2751 * This is the right place to enable back bmps_imps()
2752 */
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05302753 if (pHddCtx->hdd_wlan_suspended)
2754 {
2755 hdd_set_pwrparams(pHddCtx);
2756 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002757 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002758 goto done;
2759 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002760 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002761 wdev->iftype = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002762 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2763 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07002764 goto done;
2765 default:
2766 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2767 __func__);
2768 return -EOPNOTSUPP;
2769
2770 }
2771
2772 }
2773 else
2774 {
2775 return -EOPNOTSUPP;
2776 }
2777
2778
2779 if(pRoamProfile)
2780 {
2781 if ( LastBSSType != pRoamProfile->BSSType )
2782 {
2783 /*interface type changed update in wiphy structure*/
2784 wdev->iftype = type;
2785
2786 /*the BSS mode changed, We need to issue disconnect
2787 if connected or in IBSS disconnect state*/
2788 if ( hdd_connGetConnectedBssType(
2789 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2790 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2791 {
2792 /*need to issue a disconnect to CSR.*/
2793 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2794 if( eHAL_STATUS_SUCCESS ==
2795 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2796 pAdapter->sessionId,
2797 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2798 {
2799 wait_for_completion_interruptible_timeout(
2800 &pAdapter->disconnect_comp_var,
2801 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2802 }
2803 }
2804 }
2805 }
2806
2807done:
2808 /*set bitmask based on updated value*/
2809 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
Leo Chang6fe1f922013-06-07 19:21:24 -07002810
2811 /* Only STA mode support TM now
2812 * all other mode, TM feature should be disabled */
2813 if ( (pHddCtx->cfg_ini->thermalMitigationEnable) &&
2814 (~VOS_STA & pHddCtx->concurrency_mode) )
2815 {
2816 hddDevTmLevelChangedHandler(pHddCtx->parent_dev, 0);
2817 }
2818
Jeff Johnson295189b2012-06-20 16:38:30 -07002819#ifdef WLAN_BTAMP_FEATURE
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302820 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07002821 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2822 {
2823 //we are ok to do AMP
2824 pHddCtx->isAmpAllowed = VOS_TRUE;
2825 }
2826#endif //WLAN_BTAMP_FEATURE
2827 EXIT();
2828 return 0;
2829}
2830
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002831#ifdef FEATURE_WLAN_TDLS
2832static int wlan_hdd_tdls_add_station(struct wiphy *wiphy,
2833 struct net_device *dev, u8 *mac, bool update, tCsrStaParams *StaParams)
2834{
2835 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2836 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2837 VOS_STATUS status;
Hoonki Lee5305c3a2013-04-29 23:28:59 -07002838 hddTdlsPeer_t *pTdlsPeer;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002839
2840 ENTER();
2841
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05302842 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002843 {
2844 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2845 "Invalid arguments");
2846 return -EINVAL;
2847 }
Hoonki Lee27511902013-03-14 18:19:06 -07002848
2849 if ((eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) ||
2850 (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode))
2851 {
2852 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2853 "%s: TDLS mode is disabled OR not enabled in FW."
2854 MAC_ADDRESS_STR " Request declined.",
2855 __func__, MAC_ADDR_ARRAY(mac));
2856 return -ENOTSUPP;
2857 }
2858
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002859 if (pHddCtx->isLogpInProgress)
2860 {
2861 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2862 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07002863 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002864 return -EBUSY;
2865 }
2866
Hoonki Lee5305c3a2013-04-29 23:28:59 -07002867 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac);
2868
2869 if ( NULL == pTdlsPeer ) {
2870 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2871 "%s: " MAC_ADDRESS_STR " (update %d) not exist. return invalid",
2872 __func__, MAC_ADDR_ARRAY(mac), update);
2873 return -EINVAL;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002874 }
Hoonki Lee5305c3a2013-04-29 23:28:59 -07002875
2876 /* in add station, we accept existing valid staId if there is */
2877 if ((0 == update) &&
2878 ((pTdlsPeer->link_status >= eTDLS_LINK_CONNECTING) ||
2879 (TDLS_STA_INDEX_VALID(pTdlsPeer->staId))))
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002880 {
Hoonki Lee5305c3a2013-04-29 23:28:59 -07002881 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002882 "%s: " MAC_ADDRESS_STR
Hoonki Lee5305c3a2013-04-29 23:28:59 -07002883 " link_status %d. staId %d. add station ignored.",
2884 __func__, MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status, pTdlsPeer->staId);
2885 return 0;
2886 }
2887 /* in change station, we accept only when staId is valid */
2888 if ((1 == update) &&
2889 ((pTdlsPeer->link_status > eTDLS_LINK_CONNECTING) ||
2890 (!TDLS_STA_INDEX_VALID(pTdlsPeer->staId))))
2891 {
2892 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2893 "%s: " MAC_ADDRESS_STR
2894 " link status %d. staId %d. change station %s.",
2895 __func__, MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status, pTdlsPeer->staId,
2896 (TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) ? "ignored" : "declined");
2897 return (TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) ? 0 : -EPERM;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002898 }
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002899
2900 /* when others are on-going, we want to change link_status to idle */
Hoonki Leefb8df672013-04-10 18:20:34 -07002901 if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, mac, TRUE, TRUE))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002902 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002903 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2904 "%s: " MAC_ADDRESS_STR
2905 " TDLS setup is ongoing. Request declined.",
2906 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002907 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002908 }
2909
2910 /* first to check if we reached to maximum supported TDLS peer.
2911 TODO: for now, return -EPERM looks working fine,
2912 but need to check if any other errno fit into this category.*/
2913 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
2914 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002915 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2916 "%s: " MAC_ADDRESS_STR
2917 " TDLS Max peer already connected. Request declined.",
2918 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002919 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002920 }
2921 else
2922 {
2923 hddTdlsPeer_t *pTdlsPeer;
2924 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002925 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002926 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002927 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2928 "%s: " MAC_ADDRESS_STR " already connected. Request declined.",
2929 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002930 return -EPERM;
2931 }
2932 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002933 if (0 == update)
2934 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_CONNECTING);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002935
Jeff Johnsond75fe012013-04-06 10:53:06 -07002936 /* debug code */
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05302937 if (NULL != StaParams)
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002938 {
2939 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2940 "%s: TDLS Peer Parameters.", __func__);
Hoonki Lee66b75f32013-04-16 18:30:07 -07002941 if(StaParams->htcap_present)
2942 {
2943 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2944 "ht_capa->cap_info: %0x", StaParams->HTCap.capInfo);
2945 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2946 "ht_capa->extended_capabilities: %0x",
2947 StaParams->HTCap.extendedHtCapInfo);
2948 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002949 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2950 "params->capability: %0x",StaParams->capability);
2951 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2952 "params->ext_capab_len: %0x",StaParams->extn_capability);
Hoonki Lee66b75f32013-04-16 18:30:07 -07002953 if(StaParams->vhtcap_present)
2954 {
2955 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2956 "rxMcsMap %x rxHighest %x txMcsMap %x txHighest %x",
2957 StaParams->VHTCap.suppMcs.rxMcsMap, StaParams->VHTCap.suppMcs.rxHighest,
2958 StaParams->VHTCap.suppMcs.txMcsMap, StaParams->VHTCap.suppMcs.txHighest);
2959 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002960 {
2961 int i = 0;
Hoonki Lee5305c3a2013-04-29 23:28:59 -07002962 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "Supported rates:");
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002963 for (i = 0; i < sizeof(StaParams->supported_rates); i++)
2964 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2965 "[%d]: %x ", i, StaParams->supported_rates[i]);
2966 }
Jeff Johnsond75fe012013-04-06 10:53:06 -07002967 } /* end debug code */
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05302968 else if ((1 == update) && (NULL == StaParams))
2969 {
2970 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2971 "%s : update is true, but staParams is NULL. Error!", __func__);
2972 return -EPERM;
2973 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002974
2975 INIT_COMPLETION(pAdapter->tdls_add_station_comp);
2976
2977 if (!update)
2978 {
2979 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
2980 pAdapter->sessionId, mac);
2981 }
2982 else
2983 {
2984 status = sme_ChangeTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
2985 pAdapter->sessionId, mac, StaParams);
2986 }
2987
2988 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_add_station_comp,
2989 msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
2990
2991 if (!status)
2992 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002993 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002994 "%s: timeout waiting for tdls add station indication",
2995 __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002996 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002997 }
2998 if ( eHAL_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus)
2999 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003000 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003001 "%s: Add Station is unsucessful", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07003002 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003003 }
3004
3005 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07003006
3007error:
3008 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
3009 return -EPERM;
3010
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003011}
3012#endif
3013
Jeff Johnson295189b2012-06-20 16:38:30 -07003014static int wlan_hdd_change_station(struct wiphy *wiphy,
3015 struct net_device *dev,
3016 u8 *mac,
3017 struct station_parameters *params)
3018{
3019 VOS_STATUS status = VOS_STATUS_SUCCESS;
3020 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Gopichand Nakkala29149562013-05-10 21:43:41 +05303021 hdd_context_t *pHddCtx;
3022 hdd_station_ctx_t *pHddStaCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003023 v_MACADDR_t STAMacAddress;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003024#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003025 tCsrStaParams StaParams = {0};
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003026 tANI_U8 isBufSta = 0;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003027#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003028 ENTER();
3029
Gopichand Nakkala29149562013-05-10 21:43:41 +05303030 if ((NULL == pAdapter))
3031 {
3032 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3033 "invalid adapter ");
3034 return -EINVAL;
3035 }
3036
3037 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3038 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3039
3040 if ((NULL == pHddCtx) || (NULL == pHddStaCtx))
3041 {
3042 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3043 "invalid HDD state or HDD station context");
3044 return -EINVAL;
3045 }
3046
3047 if (pHddCtx->isLogpInProgress)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003048 {
3049 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3050 "%s:LOGP in Progress. Ignore!!!", __func__);
3051 return -EAGAIN;
3052 }
3053
Jeff Johnson295189b2012-06-20 16:38:30 -07003054 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
3055
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003056 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3057 || (pAdapter->device_mode == WLAN_HDD_P2P_GO))
Jeff Johnson295189b2012-06-20 16:38:30 -07003058 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003059 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
Jeff Johnson295189b2012-06-20 16:38:30 -07003060 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303061 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
Jeff Johnson295189b2012-06-20 16:38:30 -07003062 WLANTL_STA_AUTHENTICATED);
3063
Gopichand Nakkala29149562013-05-10 21:43:41 +05303064 if (status != VOS_STATUS_SUCCESS)
3065 {
3066 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3067 "%s: Not able to change TL state to AUTHENTICATED", __func__);
3068 return -EINVAL;
3069 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003070 }
3071 }
Hoonki Leea6d49be2013-04-05 09:43:25 -07003072 else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3073 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) {
Gopichand Nakkala29149562013-05-10 21:43:41 +05303074#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003075 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
3076 StaParams.capability = params->capability;
3077 StaParams.uapsd_queues = params->uapsd_queues;
3078 StaParams.max_sp = params->max_sp;
3079
3080 if (0 != params->ext_capab_len)
3081 vos_mem_copy(StaParams.extn_capability, params->ext_capab,
3082 sizeof(StaParams.extn_capability));
3083
3084 if (NULL != params->ht_capa)
Hoonki Lee66b75f32013-04-16 18:30:07 -07003085 {
3086 StaParams.htcap_present = 1;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003087 vos_mem_copy(&StaParams.HTCap, params->ht_capa, sizeof(tSirHTCap));
Hoonki Lee66b75f32013-04-16 18:30:07 -07003088 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003089
3090 StaParams.supported_rates_len = params->supported_rates_len;
3091
3092 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
3093 * The supported_rates array , for all the structures propogating till Add Sta
3094 * to the firmware has to be modified , if the supplicant (ieee80211) is
3095 * modified to send more rates.
3096 */
3097
3098 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
3099 */
3100 if (StaParams.supported_rates_len > SIR_MAC_MAX_SUPP_RATES)
3101 StaParams.supported_rates_len = SIR_MAC_MAX_SUPP_RATES;
3102
3103 if (0 != StaParams.supported_rates_len) {
3104 int i = 0;
3105 vos_mem_copy(StaParams.supported_rates, params->supported_rates,
3106 StaParams.supported_rates_len);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003107 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003108 "Supported Rates with Length %d", StaParams.supported_rates_len);
3109 for (i=0; i < StaParams.supported_rates_len; i++)
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003110 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003111 "[%d]: %0x", i, StaParams.supported_rates[i]);
3112 }
3113
3114 if (NULL != params->vht_capa)
Hoonki Lee66b75f32013-04-16 18:30:07 -07003115 {
3116 StaParams.vhtcap_present = 1;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003117 vos_mem_copy(&StaParams.VHTCap, params->vht_capa, sizeof(tSirVHTCap));
Hoonki Lee66b75f32013-04-16 18:30:07 -07003118 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003119
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003120 if (0 != params->ext_capab_len ) {
3121 /*Define A Macro : TODO Sunil*/
3122 if ((1<<4) & StaParams.extn_capability[3]) {
3123 isBufSta = 1;
3124 }
3125 }
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303126 status = wlan_hdd_tdls_set_peer_caps( pAdapter, mac, params->uapsd_queues,
3127 params->max_sp, isBufSta);
3128 if (VOS_STATUS_SUCCESS != status) {
3129 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3130 "%s: wlan_hdd_tdls_set_peer_caps failed!", __func__);
3131 return -EINVAL;
3132 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003133 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 1, &StaParams);
3134
3135 if (VOS_STATUS_SUCCESS != status) {
3136 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3137 "%s: sme_ChangeTdlsPeerSta failed!", __func__);
3138 return -EINVAL;
3139 }
3140 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003141#endif
Gopichand Nakkala6239acd2013-06-14 14:48:00 +05303142 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003143 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003144 return status;
3145}
3146
3147/*
Jeff Johnson295189b2012-06-20 16:38:30 -07003148 * FUNCTION: wlan_hdd_cfg80211_add_key
3149 * This function is used to initialize the key information
3150 */
3151#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003152static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003153 struct net_device *ndev,
3154 u8 key_index, bool pairwise,
3155 const u8 *mac_addr,
3156 struct key_params *params
3157 )
3158#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003159static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003160 struct net_device *ndev,
3161 u8 key_index, const u8 *mac_addr,
3162 struct key_params *params
3163 )
3164#endif
3165{
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003166 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003167 tCsrRoamSetKey setKey;
3168 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303169 int status;
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003170 v_U32_t roamId= 0xFF;
3171 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003172 hdd_hostapd_state_t *pHostapdState;
3173 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003174 eHalStatus halStatus;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303175 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003176
3177 ENTER();
3178
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303179 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3180 status = wlan_hdd_validate_context(pHddCtx);
3181
3182 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003183 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303184 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3185 "%s: HDD context is not valid", __func__);
3186 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003187 }
3188
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003189 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
3190 __func__, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003191
3192 if (CSR_MAX_NUM_KEY <= key_index)
3193 {
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003194 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003195 key_index);
3196
3197 return -EINVAL;
3198 }
3199
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003200 if (CSR_MAX_KEY_LEN < params->key_len)
3201 {
3202 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key length %d", __func__,
3203 params->key_len);
3204
3205 return -EINVAL;
3206 }
3207
3208 hddLog(VOS_TRACE_LEVEL_INFO,
3209 "%s: called with key index = %d & key length %d",
3210 __func__, key_index, params->key_len);
Jeff Johnson295189b2012-06-20 16:38:30 -07003211
3212 /*extract key idx, key len and key*/
3213 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3214 setKey.keyId = key_index;
3215 setKey.keyLength = params->key_len;
3216 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
3217
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003218 switch (params->cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07003219 {
3220 case WLAN_CIPHER_SUITE_WEP40:
3221 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
3222 break;
3223
3224 case WLAN_CIPHER_SUITE_WEP104:
3225 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
3226 break;
3227
3228 case WLAN_CIPHER_SUITE_TKIP:
3229 {
3230 u8 *pKey = &setKey.Key[0];
3231 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
3232
3233 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
3234
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003235 /*Supplicant sends the 32bytes key in this order
Jeff Johnson295189b2012-06-20 16:38:30 -07003236
3237 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003238 | Tk1 |TX-MIC | RX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003239 |--------------|----------|----------|
3240 <---16bytes---><--8bytes--><--8bytes-->
3241
3242 */
3243 /*Sme expects the 32 bytes key to be in the below order
3244
3245 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003246 | Tk1 |RX-MIC | TX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003247 |--------------|----------|----------|
3248 <---16bytes---><--8bytes--><--8bytes-->
3249 */
3250 /* Copy the Temporal Key 1 (TK1) */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003251 vos_mem_copy(pKey, params->key, 16);
Jeff Johnson295189b2012-06-20 16:38:30 -07003252
3253 /*Copy the rx mic first*/
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003254 vos_mem_copy(&pKey[16], &params->key[24], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003255
3256 /*Copy the tx mic */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003257 vos_mem_copy(&pKey[24], &params->key[16], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003258
3259
3260 break;
3261 }
3262
3263 case WLAN_CIPHER_SUITE_CCMP:
3264 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
3265 break;
3266
3267#ifdef FEATURE_WLAN_WAPI
3268 case WLAN_CIPHER_SUITE_SMS4:
3269 {
3270 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3271 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
3272 params->key, params->key_len);
3273 return 0;
3274 }
3275#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003276
Jeff Johnson295189b2012-06-20 16:38:30 -07003277#ifdef FEATURE_WLAN_CCX
3278 case WLAN_CIPHER_SUITE_KRK:
3279 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
3280 break;
3281#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003282
3283#ifdef WLAN_FEATURE_11W
3284 case WLAN_CIPHER_SUITE_AES_CMAC:
3285 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
Chet Lanctot3b5158a2013-03-31 16:45:21 -07003286 break;
Chet Lanctot186b5732013-03-18 10:26:30 -07003287#endif
3288
Jeff Johnson295189b2012-06-20 16:38:30 -07003289 default:
3290 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
3291 __func__, params->cipher);
3292 return -EOPNOTSUPP;
3293 }
3294
3295 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
3296 __func__, setKey.encType);
3297
Shailender Karmuchi642e9812013-05-30 14:34:49 -07003298 if (
Jeff Johnson295189b2012-06-20 16:38:30 -07003299#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3300 (!pairwise)
3301#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003302 (!mac_addr || is_broadcast_ether_addr(mac_addr))
Jeff Johnson295189b2012-06-20 16:38:30 -07003303#endif
Shailender Karmuchi642e9812013-05-30 14:34:49 -07003304 )
3305 {
3306 /* set group key*/
3307 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3308 "%s- %d: setting Broadcast key",
3309 __func__, __LINE__);
3310 setKey.keyDirection = eSIR_RX_ONLY;
3311 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3312 }
3313 else
3314 {
3315 /* set pairwise key*/
3316 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3317 "%s- %d: setting pairwise key",
3318 __func__, __LINE__);
3319 setKey.keyDirection = eSIR_TX_RX;
3320 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3321 }
3322 if ((WLAN_HDD_IBSS == pAdapter->device_mode) && !pairwise)
3323 {
3324 setKey.keyDirection = eSIR_TX_RX;
3325 /*Set the group key*/
3326 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3327 pAdapter->sessionId, &setKey, &roamId );
Jeff Johnson295189b2012-06-20 16:38:30 -07003328
Shailender Karmuchi642e9812013-05-30 14:34:49 -07003329 if ( 0 != status )
3330 {
3331 hddLog(VOS_TRACE_LEVEL_ERROR,
3332 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3333 return -EINVAL;
3334 }
3335 /*Save the keys here and call sme_RoamSetKey for setting
3336 the PTK after peer joins the IBSS network*/
3337 vos_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
3338 &setKey, sizeof(tCsrRoamSetKey));
3339 return status;
3340 }
Gopichand Nakkala29149562013-05-10 21:43:41 +05303341 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) ||
3342 (pAdapter->device_mode == WLAN_HDD_P2P_GO))
3343 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003344 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003345 if( pHostapdState->bssState == BSS_START )
3346 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003347 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3348
3349 if ( status != eHAL_STATUS_SUCCESS )
3350 {
3351 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3352 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3353 __LINE__, status );
3354 }
3355 }
3356
3357 /* Saving WEP keys */
3358 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
3359 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
3360 {
3361 //Save the wep key in ap context. Issue setkey after the BSS is started.
3362 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3363 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
3364 }
3365 else
3366 {
3367 //Save the key in ap context. Issue setkey after the BSS is started.
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003368 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003369 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
3370 }
3371 }
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003372 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
3373 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) )
Jeff Johnson295189b2012-06-20 16:38:30 -07003374 {
3375 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3376 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3377
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303378#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3379 if (!pairwise)
3380#else
3381 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
3382#endif
3383 {
3384 /* set group key*/
3385 if (pHddStaCtx->roam_info.deferKeyComplete)
3386 {
3387 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3388 "%s- %d: Perform Set key Complete",
3389 __func__, __LINE__);
3390 hdd_PerformRoamSetKeyComplete(pAdapter);
3391 }
3392 }
3393
Jeff Johnson295189b2012-06-20 16:38:30 -07003394 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
3395
Venkata Prathyusha Kuntupalliee2ce712013-01-17 14:09:24 -08003396 pWextState->roamProfile.Keys.defaultIndex = key_index;
3397
3398
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003399 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07003400 params->key, params->key_len);
3401
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303402
Jeff Johnson295189b2012-06-20 16:38:30 -07003403 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3404
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303405 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07003406 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303407 __func__, setKey.peerMac[0], setKey.peerMac[1],
3408 setKey.peerMac[2], setKey.peerMac[3],
3409 setKey.peerMac[4], setKey.peerMac[5],
Jeff Johnson295189b2012-06-20 16:38:30 -07003410 setKey.keyDirection);
3411
3412 vos_status = wlan_hdd_check_ula_done(pAdapter);
3413
3414 if ( vos_status != VOS_STATUS_SUCCESS )
3415 {
3416 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3417 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
3418 __LINE__, vos_status );
3419
3420 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3421
3422 return -EINVAL;
3423
3424 }
3425
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003426#ifdef WLAN_FEATURE_VOWIFI_11R
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303427 /* The supplicant may attempt to set the PTK once pre-authentication
3428 is done. Save the key in the UMAC and include it in the ADD BSS
3429 request */
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003430 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303431 if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS )
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003432 {
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303433 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3434 "%s: Update PreAuth Key success", __func__);
3435 return 0;
3436 }
3437 else if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_FAILED )
3438 {
3439 hddLog(VOS_TRACE_LEVEL_ERROR,
3440 "%s: Update PreAuth Key failed", __func__);
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303441 return -EINVAL;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003442 }
3443#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07003444
3445 /* issue set key request to SME*/
3446 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3447 pAdapter->sessionId, &setKey, &roamId );
3448
3449 if ( 0 != status )
3450 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303451 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003452 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3453 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3454 return -EINVAL;
3455 }
3456
3457
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303458 /* in case of IBSS as there was no information available about WEP keys during
3459 * IBSS join, group key intialized with NULL key, so re-initialize group key
Jeff Johnson295189b2012-06-20 16:38:30 -07003460 * with correct value*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303461 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
3462 !( ( IW_AUTH_KEY_MGMT_802_1X
3463 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
Jeff Johnson295189b2012-06-20 16:38:30 -07003464 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3465 )
3466 &&
3467 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3468 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3469 )
3470 )
3471 {
3472 setKey.keyDirection = eSIR_RX_ONLY;
3473 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3474
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303475 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07003476 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303477 __func__, setKey.peerMac[0], setKey.peerMac[1],
3478 setKey.peerMac[2], setKey.peerMac[3],
3479 setKey.peerMac[4], setKey.peerMac[5],
Jeff Johnson295189b2012-06-20 16:38:30 -07003480 setKey.keyDirection);
3481
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303482 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07003483 pAdapter->sessionId, &setKey, &roamId );
3484
3485 if ( 0 != status )
3486 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303487 hddLog(VOS_TRACE_LEVEL_ERROR,
3488 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07003489 __func__, status);
3490 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3491 return -EINVAL;
3492 }
3493 }
3494 }
3495
3496 return 0;
3497}
3498
3499/*
3500 * FUNCTION: wlan_hdd_cfg80211_get_key
3501 * This function is used to get the key information
3502 */
3503#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303504static int wlan_hdd_cfg80211_get_key(
3505 struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003506 struct net_device *ndev,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303507 u8 key_index, bool pairwise,
Jeff Johnson295189b2012-06-20 16:38:30 -07003508 const u8 *mac_addr, void *cookie,
3509 void (*callback)(void *cookie, struct key_params*)
3510 )
3511#else
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,
3515 u8 key_index, const u8 *mac_addr, void *cookie,
3516 void (*callback)(void *cookie, struct key_params*)
3517 )
3518#endif
3519{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303520 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003521 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3522 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
3523 struct key_params params;
3524
3525 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303526
Jeff Johnson295189b2012-06-20 16:38:30 -07003527 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3528 __func__,pAdapter->device_mode);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303529
Jeff Johnson295189b2012-06-20 16:38:30 -07003530 memset(&params, 0, sizeof(params));
3531
3532 if (CSR_MAX_NUM_KEY <= key_index)
3533 {
3534 return -EINVAL;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303535 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003536
3537 switch(pRoamProfile->EncryptionType.encryptionType[0])
3538 {
3539 case eCSR_ENCRYPT_TYPE_NONE:
3540 params.cipher = IW_AUTH_CIPHER_NONE;
3541 break;
3542
3543 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3544 case eCSR_ENCRYPT_TYPE_WEP40:
3545 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3546 break;
3547
3548 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3549 case eCSR_ENCRYPT_TYPE_WEP104:
3550 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3551 break;
3552
3553 case eCSR_ENCRYPT_TYPE_TKIP:
3554 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3555 break;
3556
3557 case eCSR_ENCRYPT_TYPE_AES:
3558 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3559 break;
3560
3561 default:
3562 params.cipher = IW_AUTH_CIPHER_NONE;
3563 break;
3564 }
3565
3566 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3567 params.seq_len = 0;
3568 params.seq = NULL;
3569 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3570 callback(cookie, &params);
3571 return 0;
3572}
3573
3574/*
3575 * FUNCTION: wlan_hdd_cfg80211_del_key
3576 * This function is used to delete the key information
3577 */
3578#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303579static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003580 struct net_device *ndev,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303581 u8 key_index,
3582 bool pairwise,
Jeff Johnson295189b2012-06-20 16:38:30 -07003583 const u8 *mac_addr
3584 )
3585#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303586static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003587 struct net_device *ndev,
3588 u8 key_index,
3589 const u8 *mac_addr
3590 )
3591#endif
3592{
3593 int status = 0;
3594
3595 //This code needs to be revisited. There is sme_removeKey API, we should
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303596 //plan to use that. After the change to use correct index in setkey,
Jeff Johnson295189b2012-06-20 16:38:30 -07003597 //it is observed that this is invalidating peer
3598 //key index whenever re-key is done. This is affecting data link.
3599 //It should be ok to ignore del_key.
3600#if 0
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303601 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3602 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003603 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3604 tCsrRoamSetKey setKey;
3605 v_U32_t roamId= 0xFF;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303606
Jeff Johnson295189b2012-06-20 16:38:30 -07003607 ENTER();
3608
3609 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3610 __func__,pAdapter->device_mode);
3611
3612 if (CSR_MAX_NUM_KEY <= key_index)
3613 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303614 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003615 key_index);
3616
3617 return -EINVAL;
3618 }
3619
3620 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3621 setKey.keyId = key_index;
3622
3623 if (mac_addr)
3624 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3625 else
3626 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3627
3628 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3629
3630 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003631 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303632 )
3633 {
3634
3635 hdd_hostapd_state_t *pHostapdState =
Jeff Johnson295189b2012-06-20 16:38:30 -07003636 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3637 if( pHostapdState->bssState == BSS_START)
3638 {
3639 status = WLANSAP_SetKeySta( pVosContext, &setKey);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303640
Jeff Johnson295189b2012-06-20 16:38:30 -07003641 if ( status != eHAL_STATUS_SUCCESS )
3642 {
3643 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3644 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3645 __LINE__, status );
3646 }
3647 }
3648 }
3649 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303650 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003651 )
3652 {
3653 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3654
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303655 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3656
3657 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07003658 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303659 __func__, setKey.peerMac[0], setKey.peerMac[1],
3660 setKey.peerMac[2], setKey.peerMac[3],
Jeff Johnson295189b2012-06-20 16:38:30 -07003661 setKey.peerMac[4], setKey.peerMac[5]);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303662 if(pAdapter->sessionCtx.station.conn_info.connState ==
3663 eConnectionState_Associated)
Jeff Johnson295189b2012-06-20 16:38:30 -07003664 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303665 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07003666 pAdapter->sessionId, &setKey, &roamId );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303667
Jeff Johnson295189b2012-06-20 16:38:30 -07003668 if ( 0 != status )
3669 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303670 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003671 "%s: sme_RoamSetKey failure, returned %d",
3672 __func__, status);
3673 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3674 return -EINVAL;
3675 }
3676 }
3677 }
3678#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003679 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003680 return status;
3681}
3682
3683/*
3684 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3685 * This function is used to set the default tx key index
3686 */
3687#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3688static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3689 struct net_device *ndev,
3690 u8 key_index,
3691 bool unicast, bool multicast)
3692#else
3693static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3694 struct net_device *ndev,
3695 u8 key_index)
3696#endif
3697{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303698 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303699 int status;
Gopichand Nakkala29149562013-05-10 21:43:41 +05303700 hdd_wext_state_t *pWextState;
3701 hdd_station_ctx_t *pHddStaCtx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303702 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003703
3704 ENTER();
3705
Gopichand Nakkala29149562013-05-10 21:43:41 +05303706 if ((NULL == pAdapter))
3707 {
3708 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3709 "invalid adapter");
3710 return -EINVAL;
3711 }
3712
3713 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3714 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3715
3716 if ((NULL == pWextState) || (NULL == pHddStaCtx))
3717 {
3718 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3719 "invalid Wext state or HDD context");
3720 return -EINVAL;
3721 }
3722
Jeff Johnson295189b2012-06-20 16:38:30 -07003723 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3724 __func__,pAdapter->device_mode, key_index);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303725
Jeff Johnson295189b2012-06-20 16:38:30 -07003726 if (CSR_MAX_NUM_KEY <= key_index)
3727 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303728 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003729 key_index);
3730
3731 return -EINVAL;
3732 }
3733
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303734 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3735 status = wlan_hdd_validate_context(pHddCtx);
3736
3737 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003738 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303739 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3740 "%s: HDD context is not valid", __func__);
3741 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003742 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303743
Jeff Johnson295189b2012-06-20 16:38:30 -07003744 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003745 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303746 )
Jeff Johnson295189b2012-06-20 16:38:30 -07003747 {
Gopichand Nakkala29149562013-05-10 21:43:41 +05303748 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
Jeff Johnson295189b2012-06-20 16:38:30 -07003749 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303750 (eCSR_ENCRYPT_TYPE_AES !=
Jeff Johnson295189b2012-06-20 16:38:30 -07003751 pWextState->roamProfile.EncryptionType.encryptionType[0])
3752 )
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303753 {
3754 /* if default key index is not same as previous one,
Jeff Johnson295189b2012-06-20 16:38:30 -07003755 * then update the default key index */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303756
Jeff Johnson295189b2012-06-20 16:38:30 -07003757 tCsrRoamSetKey setKey;
3758 v_U32_t roamId= 0xFF;
3759 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303760
3761 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07003762 __func__, key_index);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303763
Jeff Johnson295189b2012-06-20 16:38:30 -07003764 Keys->defaultIndex = (u8)key_index;
3765 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3766 setKey.keyId = key_index;
3767 setKey.keyLength = Keys->KeyLength[key_index];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303768
3769 vos_mem_copy(&setKey.Key[0],
3770 &Keys->KeyMaterial[key_index][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07003771 Keys->KeyLength[key_index]);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303772
Gopichand Nakkala29149562013-05-10 21:43:41 +05303773 setKey.keyDirection = eSIR_TX_RX;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303774
3775 vos_mem_copy(setKey.peerMac,
Jeff Johnson295189b2012-06-20 16:38:30 -07003776 &pHddStaCtx->conn_info.bssId[0],
3777 WNI_CFG_BSSID_LEN);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303778
Gopichand Nakkala29149562013-05-10 21:43:41 +05303779 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
3780 pWextState->roamProfile.EncryptionType.encryptionType[0] ==
3781 eCSR_ENCRYPT_TYPE_WEP104)
3782 {
3783 /*In the case of dynamic wep supplicant hardcodes DWEP type to eCSR_ENCRYPT_TYPE_WEP104
3784 even though ap is configured for WEP-40 encryption. In this canse the key length
3785 is 5 but the encryption type is 104 hence checking the key langht(5) and encryption
3786 type(104) and switching encryption type to 40*/
3787 pWextState->roamProfile.EncryptionType.encryptionType[0] =
3788 eCSR_ENCRYPT_TYPE_WEP40;
3789 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
3790 eCSR_ENCRYPT_TYPE_WEP40;
3791 }
3792
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303793 setKey.encType =
Jeff Johnson295189b2012-06-20 16:38:30 -07003794 pWextState->roamProfile.EncryptionType.encryptionType[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303795
Jeff Johnson295189b2012-06-20 16:38:30 -07003796 /* issue set key request */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303797 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07003798 pAdapter->sessionId, &setKey, &roamId );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303799
Jeff Johnson295189b2012-06-20 16:38:30 -07003800 if ( 0 != status )
3801 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303802 hddLog(VOS_TRACE_LEVEL_ERROR,
3803 "%s: sme_RoamSetKey failed, returned %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003804 status);
3805 return -EINVAL;
3806 }
3807 }
3808 }
3809
3810 /* In SoftAp mode setting key direction for default mode */
3811 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3812 {
3813 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3814 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3815 (eCSR_ENCRYPT_TYPE_AES !=
3816 pWextState->roamProfile.EncryptionType.encryptionType[0])
3817 )
3818 {
3819 /* Saving key direction for default key index to TX default */
3820 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3821 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3822 }
3823 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303824
Jeff Johnson295189b2012-06-20 16:38:30 -07003825 return status;
3826}
3827
Jeff Johnson295189b2012-06-20 16:38:30 -07003828/*
3829 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3830 * This function is used to inform the BSS details to nl80211 interface.
3831 */
3832static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3833 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3834{
3835 struct net_device *dev = pAdapter->dev;
3836 struct wireless_dev *wdev = dev->ieee80211_ptr;
3837 struct wiphy *wiphy = wdev->wiphy;
3838 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3839 int chan_no;
3840 int ie_length;
3841 const char *ie;
3842 unsigned int freq;
3843 struct ieee80211_channel *chan;
3844 int rssi = 0;
3845 struct cfg80211_bss *bss = NULL;
3846
3847 ENTER();
3848
3849 if( NULL == pBssDesc )
3850 {
3851 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3852 return bss;
3853 }
3854
3855 chan_no = pBssDesc->channelId;
3856 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3857 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3858
3859 if( NULL == ie )
3860 {
3861 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3862 return bss;
3863 }
3864
3865#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3866 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3867 {
3868 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3869 }
3870 else
3871 {
3872 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3873 }
3874#else
3875 freq = ieee80211_channel_to_frequency(chan_no);
3876#endif
3877
3878 chan = __ieee80211_get_channel(wiphy, freq);
3879
3880 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3881 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3882 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3883 if (bss == NULL)
3884 {
3885 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3886
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303887 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3888 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
Jeff Johnson295189b2012-06-20 16:38:30 -07003889 pBssDesc->capabilityInfo,
3890 pBssDesc->beaconInterval, ie, ie_length,
3891 rssi, GFP_KERNEL ));
3892}
3893 else
3894 {
3895 return bss;
3896 }
3897}
3898
3899
3900
3901/*
3902 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3903 * This function is used to inform the BSS details to nl80211 interface.
3904 */
3905struct cfg80211_bss*
3906wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3907 tSirBssDescription *bss_desc
3908 )
3909{
3910 /*
3911 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3912 already exists in bss data base of cfg80211 for that particular BSS ID.
3913 Using cfg80211_inform_bss_frame to update the bss entry instead of
3914 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3915 now there is no possibility to get the mgmt(probe response) frame from PE,
3916 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3917 cfg80211_inform_bss_frame.
3918 */
3919 struct net_device *dev = pAdapter->dev;
3920 struct wireless_dev *wdev = dev->ieee80211_ptr;
3921 struct wiphy *wiphy = wdev->wiphy;
3922 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003923#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3924 qcom_ie_age *qie_age = NULL;
3925 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3926#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003927 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003928#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003929 const char *ie =
3930 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3931 unsigned int freq;
3932 struct ieee80211_channel *chan;
3933 struct ieee80211_mgmt *mgmt =
3934 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3935 struct cfg80211_bss *bss_status = NULL;
3936 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3937 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003938#ifdef WLAN_OPEN_SOURCE
3939 struct timespec ts;
3940#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003941
3942 ENTER();
3943
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003944 if (!mgmt)
3945 return NULL;
3946
Jeff Johnson295189b2012-06-20 16:38:30 -07003947 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003948
3949#ifdef WLAN_OPEN_SOURCE
3950 /* Android does not want the timestamp from the frame.
3951 Instead it wants a monotonic increasing value */
3952 get_monotonic_boottime(&ts);
3953 mgmt->u.probe_resp.timestamp =
3954 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3955#else
3956 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003957 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3958 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003959
3960#endif
3961
Jeff Johnson295189b2012-06-20 16:38:30 -07003962 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3963 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003964
3965#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3966 /* GPS Requirement: need age ie per entry. Using vendor specific. */
3967 /* Assuming this is the last IE, copy at the end */
3968 ie_length -=sizeof(qcom_ie_age);
3969 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
3970 qie_age->element_id = QCOM_VENDOR_IE_ID;
3971 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
3972 qie_age->oui_1 = QCOM_OUI1;
3973 qie_age->oui_2 = QCOM_OUI2;
3974 qie_age->oui_3 = QCOM_OUI3;
3975 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
3976 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
3977#endif
3978
Jeff Johnson295189b2012-06-20 16:38:30 -07003979 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
Gopichand Nakkalad908ec82013-05-16 19:32:19 +05303980 if (bss_desc->fProbeRsp)
3981 {
3982 mgmt->frame_control |=
3983 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3984 }
3985 else
3986 {
3987 mgmt->frame_control |=
3988 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
3989 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003990
3991#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303992 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07003993 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3994 {
3995 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3996 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303997 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07003998 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3999
4000 {
4001 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
4002 }
4003 else
4004 {
4005 kfree(mgmt);
4006 return NULL;
4007 }
4008#else
4009 freq = ieee80211_channel_to_frequency(chan_no);
4010#endif
4011 chan = __ieee80211_get_channel(wiphy, freq);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08004012 /*when the band is changed on the fly using the GUI, three things are done
4013 * 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)
4014 * as part of the scan abort, message willbe queued to PE and we proceed with flushing and changinh the band.
4015 * pe will stop the scanning further and report back the results what ever it had till now by calling the call back function.
4016 * if the time between update band and scandone call back is sufficent enough the band change reflects in SME, SME validates the channels
4017 * and discards the channels correponding to previous band and calls back with zero bss results.
4018 * 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
4019 * all the channels correponding to previous band.this is due to race condition.but those channels are invalid to the new band and so
4020 * this function __ieee80211_get_channel will return NULL.Each time we report scan result with this pointer null warning kernel trace is printed.
4021 * if the scan results contain large number of APs continuosly kernel warning trace is printed and it will lead to apps watch dog bark.
4022 * So drop the bss and continue to next bss.
4023 */
4024 if(chan == NULL)
4025 {
4026 hddLog(VOS_TRACE_LEVEL_INFO, "%s chan pointer is NULL", __func__);
Chilam Ngc4244af2013-04-01 15:37:32 -07004027 kfree(mgmt);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08004028 return NULL;
4029 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004030 /*To keep the rssi icon of the connected AP in the scan window
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304031 *and the rssi icon of the wireless networks in sync
Jeff Johnson295189b2012-06-20 16:38:30 -07004032 * */
4033 if (( eConnectionState_Associated ==
4034 pAdapter->sessionCtx.station.conn_info.connState ) &&
4035 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
4036 pAdapter->sessionCtx.station.conn_info.bssId,
4037 WNI_CFG_BSSID_LEN)))
4038 {
4039 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
4040 rssi = (pAdapter->rssi * 100);
4041 }
4042 else
4043 {
4044 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
4045 }
4046
4047 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
4048 frame_len, rssi, GFP_KERNEL);
4049 kfree(mgmt);
4050 return bss_status;
4051}
4052
4053/*
4054 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
4055 * This function is used to update the BSS data base of CFG8011
4056 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304057struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07004058 tCsrRoamInfo *pRoamInfo
4059 )
4060{
4061 tCsrRoamConnectedProfile roamProfile;
4062 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4063 struct cfg80211_bss *bss = NULL;
4064
4065 ENTER();
4066
4067 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
4068 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
4069
4070 if (NULL != roamProfile.pBssDesc)
4071 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304072 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07004073 &roamProfile);
4074
4075 if (NULL == bss)
4076 {
4077 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
4078 __func__);
4079 }
4080
4081 sme_RoamFreeConnectProfile(hHal, &roamProfile);
4082 }
4083 else
4084 {
4085 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
4086 __func__);
4087 }
4088 return bss;
4089}
4090
4091/*
4092 * FUNCTION: wlan_hdd_cfg80211_update_bss
4093 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304094static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
4095 hdd_adapter_t *pAdapter
Jeff Johnson295189b2012-06-20 16:38:30 -07004096 )
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304097{
Jeff Johnson295189b2012-06-20 16:38:30 -07004098 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4099 tCsrScanResultInfo *pScanResult;
4100 eHalStatus status = 0;
4101 tScanResultHandle pResult;
4102 struct cfg80211_bss *bss_status = NULL;
4103
4104 ENTER();
4105
4106 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4107 {
4108 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
4109 return -EAGAIN;
4110 }
4111
4112 /*
4113 * start getting scan results and populate cgf80211 BSS database
4114 */
4115 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
4116
4117 /* no scan results */
4118 if (NULL == pResult)
4119 {
4120 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
4121 return status;
4122 }
4123
4124 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
4125
4126 while (pScanResult)
4127 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304128 /*
4129 * cfg80211_inform_bss() is not updating ie field of bss entry, if
4130 * entry already exists in bss data base of cfg80211 for that
4131 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
4132 * bss entry instead of cfg80211_inform_bss, But this call expects
4133 * mgmt packet as input. As of now there is no possibility to get
4134 * the mgmt(probe response) frame from PE, converting bss_desc to
Jeff Johnson295189b2012-06-20 16:38:30 -07004135 * ieee80211_mgmt(probe response) and passing to c
4136 * fg80211_inform_bss_frame.
4137 * */
4138
4139 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
4140 &pScanResult->BssDescriptor);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304141
Jeff Johnson295189b2012-06-20 16:38:30 -07004142
4143 if (NULL == bss_status)
4144 {
4145 hddLog(VOS_TRACE_LEVEL_INFO,
4146 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
4147 }
4148 else
4149 {
Yue Maf49ba872013-08-19 12:04:25 -07004150 cfg80211_put_bss(
4151#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
4152 wiphy,
4153#endif
4154 bss_status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004155 }
4156
4157 pScanResult = sme_ScanResultGetNext(hHal, pResult);
4158 }
4159
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304160 sme_ScanResultPurge(hHal, pResult);
Jeff Johnson295189b2012-06-20 16:38:30 -07004161
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304162 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004163}
4164
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004165void
4166hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
4167{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304168 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004169 "%02X:%02X:%02X:%02X:%02X:%02X\n",
4170 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
4171 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004172} /****** end hddPrintMacAddr() ******/
4173
4174void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004175hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004176{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304177 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004178 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
4179 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
4180 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
4181 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004182} /****** end hddPrintPmkId() ******/
4183
4184//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
4185//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
4186
4187//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
4188//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
4189
4190#define dump_bssid(bssid) \
4191 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004192 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
4193 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
4194 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004195 }
4196
4197#define dump_pmkid(pMac, pmkid) \
4198 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004199 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
4200 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
4201 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004202 }
4203
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07004204#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004205/*
4206 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
4207 * This function is used to notify the supplicant of a new PMKSA candidate.
4208 */
4209int wlan_hdd_cfg80211_pmksa_candidate_notify(
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304210 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004211 int index, bool preauth )
4212{
Jeff Johnsone7245742012-09-05 17:12:55 -07004213#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004214 struct net_device *dev = pAdapter->dev;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004215 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004216
4217 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07004218 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004219
4220 if( NULL == pRoamInfo )
4221 {
4222 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
4223 return -EINVAL;
4224 }
4225
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004226 if (eANI_BOOLEAN_TRUE == hdd_is_okc_mode_enabled(pHddCtx))
4227 {
4228 dump_bssid(pRoamInfo->bssid);
4229 cfg80211_pmksa_candidate_notify(dev, index,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004230 pRoamInfo->bssid, preauth, GFP_KERNEL);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004231 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004232#endif /* FEATURE_WLAN_OKC */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304233 return 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004234}
4235#endif //FEATURE_WLAN_LFR
4236
Jeff Johnson295189b2012-06-20 16:38:30 -07004237/*
4238 * FUNCTION: hdd_cfg80211_scan_done_callback
4239 * scanning callback function, called after finishing scan
4240 *
4241 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304242static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
Jeff Johnson295189b2012-06-20 16:38:30 -07004243 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
4244{
4245 struct net_device *dev = (struct net_device *) pContext;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304246 //struct wireless_dev *wdev = dev->ieee80211_ptr;
Jeff Johnson295189b2012-06-20 16:38:30 -07004247 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004248 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4249 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004250 struct cfg80211_scan_request *req = NULL;
4251 int ret = 0;
4252
4253 ENTER();
4254
4255 hddLog(VOS_TRACE_LEVEL_INFO,
4256 "%s called with halHandle = %p, pContext = %p,"
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304257 "scanID = %d, returned status = %d\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07004258 __func__, halHandle, pContext, (int) scanId, (int) status);
4259
4260 //Block on scan req completion variable. Can't wait forever though.
4261 ret = wait_for_completion_interruptible_timeout(
4262 &pScanInfo->scan_req_completion_event,
4263 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
4264 if (!ret)
4265 {
4266 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004267 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004268 }
4269
4270 if(pScanInfo->mScanPending != VOS_TRUE)
4271 {
4272 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004273 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004274 }
4275
4276 /* Check the scanId */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304277 if (pScanInfo->scanId != scanId)
Jeff Johnson295189b2012-06-20 16:38:30 -07004278 {
4279 hddLog(VOS_TRACE_LEVEL_INFO,
4280 "%s called with mismatched scanId pScanInfo->scanId = %d "
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304281 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
Jeff Johnson295189b2012-06-20 16:38:30 -07004282 (int) scanId);
4283 }
4284
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304285 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07004286 pAdapter);
4287
4288 if (0 > ret)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304289 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004290
4291
4292 /* If any client wait scan result through WEXT
4293 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004294 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07004295 {
4296 /* The other scan request waiting for current scan finish
4297 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004298 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004299 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004300 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004301 }
4302 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004303 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004304 {
4305 struct net_device *dev = pAdapter->dev;
4306 union iwreq_data wrqu;
4307 int we_event;
4308 char *msg;
4309
4310 memset(&wrqu, '\0', sizeof(wrqu));
4311 we_event = SIOCGIWSCAN;
4312 msg = NULL;
4313 wireless_send_event(dev, we_event, &wrqu, msg);
4314 }
4315 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004316 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004317
4318 /* Get the Scan Req */
4319 req = pAdapter->request;
4320
4321 if (!req)
4322 {
4323 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004324 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07004325 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004326 }
4327
4328 /*
4329 * setting up 0, just in case.
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304330 */
Jeff Johnson295189b2012-06-20 16:38:30 -07004331 req->n_ssids = 0;
4332 req->n_channels = 0;
4333 req->ie = 0;
4334
Jeff Johnson295189b2012-06-20 16:38:30 -07004335 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004336 /* Scan is no longer pending */
4337 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004338
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07004339 /*
4340 * cfg80211_scan_done informing NL80211 about completion
4341 * of scanning
4342 */
4343 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004344 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004345
Jeff Johnsone7245742012-09-05 17:12:55 -07004346allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004347 /* release the wake lock at the end of the scan*/
4348 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004349
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004350 /* Acquire wakelock to handle the case where APP's tries to suspend
4351 * immediatly after the driver gets connect request(i.e after scan)
4352 * from supplicant, this result in app's is suspending and not able
4353 * to process the connect request to AP */
Amar Singhal6144c002013-05-03 16:11:42 -07004354 hdd_allow_suspend_timeout(1000);
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004355
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004356#ifdef FEATURE_WLAN_TDLS
4357 wlan_hdd_tdls_scan_done_callback(pAdapter);
4358#endif
4359
Jeff Johnson295189b2012-06-20 16:38:30 -07004360 EXIT();
4361 return 0;
4362}
4363
4364/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004365 * FUNCTION: hdd_isScanAllowed
4366 * Go through each adapter and check if scan allowed
4367 *
4368 */
4369v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
4370{
4371 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4372 hdd_station_ctx_t *pHddStaCtx = NULL;
4373 hdd_adapter_t *pAdapter = NULL;
4374 VOS_STATUS status = 0;
4375 v_U8_t staId = 0;
4376 v_U8_t *staMac = NULL;
4377
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05304378 if (VOS_TIMER_STATE_RUNNING ==
4379 vos_timer_getCurrentState(&pHddCtx->hdd_p2p_go_conn_is_in_progress))
4380 {
4381 hddLog(VOS_TRACE_LEVEL_INFO,
4382 "%s: Connection is in progress, Do not allow the scan", __func__);
4383 return VOS_FALSE;
4384 }
4385
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004386 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");
5858 hdd_abort_mac_scan(pHddCtx);
5859 }
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 {
6922 if(pAdapter->aStaInfo[i].isUsed)
6923 {
6924 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
6925 hddLog(VOS_TRACE_LEVEL_INFO,
6926 "%s: Delete STA with MAC::"
6927 "%02x:%02x:%02x:%02x:%02x:%02x",
6928 __func__,
6929 macAddr[0], macAddr[1], macAddr[2],
6930 macAddr[3], macAddr[4], macAddr[5]);
6931 hdd_softap_sta_deauth(pAdapter, macAddr);
6932 }
6933 }
6934 }
6935 else
6936 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006937
6938 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
6939 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6940 {
6941 hddLog(VOS_TRACE_LEVEL_INFO,
6942 "%s: Skip this DEL STA as this is not used::"
6943 "%02x:%02x:%02x:%02x:%02x:%02x",
6944 __func__,
6945 mac[0], mac[1], mac[2],
6946 mac[3], mac[4], mac[5]);
6947 return -ENOENT;
6948 }
6949
6950 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
6951 {
6952 hddLog(VOS_TRACE_LEVEL_INFO,
6953 "%s: Skip this DEL STA as deauth is in progress::"
6954 "%02x:%02x:%02x:%02x:%02x:%02x",
6955 __func__,
6956 mac[0], mac[1], mac[2],
6957 mac[3], mac[4], mac[5]);
6958 return -ENOENT;
6959 }
6960
6961 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
6962
Jeff Johnson295189b2012-06-20 16:38:30 -07006963 hddLog(VOS_TRACE_LEVEL_INFO,
6964 "%s: Delete STA with MAC::"
6965 "%02x:%02x:%02x:%02x:%02x:%02x",
6966 __func__,
6967 mac[0], mac[1], mac[2],
6968 mac[3], mac[4], mac[5]);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006969
6970 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
6971 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6972 {
6973 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
6974 hddLog(VOS_TRACE_LEVEL_INFO,
6975 "%s: STA removal failed for ::"
6976 "%02x:%02x:%02x:%02x:%02x:%02x",
6977 __func__,
6978 mac[0], mac[1], mac[2],
6979 mac[3], mac[4], mac[5]);
6980 return -ENOENT;
6981 }
6982
Jeff Johnson295189b2012-06-20 16:38:30 -07006983 }
6984 }
6985
6986 EXIT();
6987
6988 return 0;
6989}
6990
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006991static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
6992 struct net_device *dev, u8 *mac, struct station_parameters *params)
6993{
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006994 int status = -EPERM;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006995#ifdef FEATURE_WLAN_TDLS
6996 u32 mask, set;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006997 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006998 mask = params->sta_flags_mask;
6999
7000 set = params->sta_flags_set;
7001
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007002#ifdef WLAN_FEATURE_TDLS_DEBUG
7003 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7004 "%s: mask 0x%x set 0x%x " MAC_ADDRESS_STR,
7005 __func__, mask, set, MAC_ADDR_ARRAY(mac));
7006#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007007
7008 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
7009 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08007010 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007011 }
7012 }
7013#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007014 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07007015}
7016
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007017
7018#ifdef FEATURE_WLAN_LFR
7019static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07007020 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007021{
7022#define MAX_PMKSAIDS_IN_CACHE 8
7023 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307024 static tANI_U32 i; // HDD Local Cache index
7025 tANI_U32 j=0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007026 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7027 tHalHandle halHandle;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307028 eHalStatus result;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307029 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007030 tANI_U8 BSSIDMatched = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307031 hdd_context_t *pHddCtx;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307032
Jeff Johnsone7245742012-09-05 17:12:55 -07007033 ENTER();
7034
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307035 // Validate pAdapter
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307036 if ( NULL == pAdapter )
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007037 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307038 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007039 return -EINVAL;
7040 }
7041
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307042 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7043 status = wlan_hdd_validate_context(pHddCtx);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007044
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307045 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007046 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307047 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7048 "%s: HDD context is not valid", __func__);
7049 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007050 }
7051
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307052 // Retrieve halHandle
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007053 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
7054
7055 for (j = 0; j < i; j++)
7056 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307057 if(vos_mem_compare(PMKIDCache[j].BSSID,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007058 pmksa->bssid, WNI_CFG_BSSID_LEN))
7059 {
7060 /* BSSID matched previous entry. Overwrite it. */
7061 BSSIDMatched = 1;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307062 vos_mem_copy(PMKIDCache[j].BSSID,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007063 pmksa->bssid, WNI_CFG_BSSID_LEN);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307064 vos_mem_copy(PMKIDCache[j].PMKID,
7065 pmksa->pmkid,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007066 CSR_RSN_PMKID_SIZE);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307067 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007068 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007069 dump_bssid(pmksa->bssid);
7070 dump_pmkid(halHandle, pmksa->pmkid);
7071 break;
7072 }
7073 }
7074
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07007075 /* Check we compared all entries,if then take the first slot now */
7076 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
7077
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007078 if (!BSSIDMatched)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307079 {
7080 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
7081 vos_mem_copy(PMKIDCache[i].BSSID,
7082 pmksa->bssid, ETHER_ADDR_LEN);
7083 vos_mem_copy(PMKIDCache[i].PMKID,
7084 pmksa->pmkid,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007085 CSR_RSN_PMKID_SIZE);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307086 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007087 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007088 dump_bssid(pmksa->bssid);
7089 dump_pmkid(halHandle, pmksa->pmkid);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307090 // Increment the HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007091 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307092 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007093 }
7094
7095
7096 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307097 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007098 // __func__, i );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307099 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007100 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007101 // Finally set the PMKSA ID Cache in CSR
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307102 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
7103 PMKIDCache,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007104 i );
7105 return 0;
7106}
7107
7108
7109static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07007110 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007111{
Jeff Johnsone7245742012-09-05 17:12:55 -07007112 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007113 // TODO: Implement this later.
7114 return 0;
7115}
7116
7117static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
7118{
Jeff Johnsone7245742012-09-05 17:12:55 -07007119 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007120 // TODO: Implement this later.
7121 return 0;
7122}
7123#endif
7124
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007125#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307126static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007127 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
7128{
7129 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7130 hdd_station_ctx_t *pHddStaCtx;
7131
7132 if (NULL == pAdapter)
7133 {
7134 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
7135 return -ENODEV;
7136 }
7137
7138 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7139
7140 // Added for debug on reception of Re-assoc Req.
7141 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
7142 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307143 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007144 ftie->ie_len);
7145 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
7146 }
7147
7148#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307149 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007150 ftie->ie_len);
7151#endif
7152
7153 // Pass the received FT IEs to SME
Gopichand Nakkala356fb102013-03-06 12:34:04 +05307154 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
7155 (const u8 *)ftie->ie,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007156 ftie->ie_len);
7157 return 0;
7158}
7159#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007160
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307161#ifdef FEATURE_WLAN_SCAN_PNO
7162
7163void hdd_cfg80211_sched_scan_done_callback(void *callbackContext,
7164 tSirPrefNetworkFoundInd *pPrefNetworkFoundInd)
7165{
7166 int ret;
7167 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
7168 hdd_context_t *pHddCtx;
7169
7170 if (NULL == pAdapter)
7171 {
7172 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7173 "%s: HDD adapter is Null", __func__);
7174 return ;
7175 }
7176
7177 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7178 if (NULL == pHddCtx)
7179 {
7180 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7181 "%s: HDD context is Null!!!", __func__);
7182 return ;
7183 }
7184
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307185 spin_lock(&pHddCtx->schedScan_lock);
7186 if (TRUE == pHddCtx->isWiphySuspended)
7187 {
7188 pHddCtx->isSchedScanUpdatePending = TRUE;
7189 spin_unlock(&pHddCtx->schedScan_lock);
7190 hddLog(VOS_TRACE_LEVEL_INFO,
7191 "%s: Update cfg80211 scan database after it resume", __func__);
7192 return ;
7193 }
7194 spin_unlock(&pHddCtx->schedScan_lock);
7195
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307196 ret = wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter);
7197
7198 if (0 > ret)
7199 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
7200
7201 cfg80211_sched_scan_results(pHddCtx->wiphy);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307202 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7203 "%s: cfg80211 scan result database updated", __func__);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307204}
7205
7206/*
7207 * FUNCTION: wlan_hdd_cfg80211_sched_scan_start
7208 * NL interface to enable PNO
7209 */
7210static int wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy,
7211 struct net_device *dev, struct cfg80211_sched_scan_request *request)
7212{
7213 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7214 tpSirPNOScanReq pPnoRequest = NULL;
7215 hdd_context_t *pHddCtx;
7216 tHalHandle hHal;
7217 v_U32_t i, indx, num_ch;
7218 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
7219 u8 channels_allowed[WNI_CFG_VALID_CHANNEL_LIST_LEN];
7220 v_U32_t num_channels_allowed = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7221 eHalStatus status = eHAL_STATUS_FAILURE;
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307222 int ret = 0;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307223
7224 if (NULL == pAdapter)
7225 {
7226 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7227 "%s: HDD adapter is Null", __func__);
7228 return -ENODEV;
7229 }
7230
7231 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307232 ret = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307233
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307234 if (0 != ret)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307235 {
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05307236 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7237 "%s: HDD context is not valid", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307238 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307239 }
7240
7241 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
7242 if (NULL == hHal)
7243 {
7244 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7245 "%s: HAL context is Null!!!", __func__);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307246 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307247 }
7248
7249 pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq));
7250 if (NULL == pPnoRequest)
7251 {
7252 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7253 "%s: vos_mem_malloc failed", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307254 return -ENOMEM;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307255 }
7256
7257 pPnoRequest->enable = 1; /*Enable PNO */
7258 pPnoRequest->ucNetworksCount = request->n_match_sets;
7259
7260 if (( !pPnoRequest->ucNetworksCount ) ||
7261 ( pPnoRequest->ucNetworksCount > SIR_PNO_MAX_SUPP_NETWORKS ))
7262 {
7263 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7264 "Network input is not correct");
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307265 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307266 goto error;
7267 }
7268
7269 if ( SIR_PNO_MAX_NETW_CHANNELS_EX < request->n_channels )
7270 {
7271 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7272 "Incorrect number of channels");
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307273 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307274 goto error;
7275 }
7276
7277 /* Framework provides one set of channels(all)
7278 * common for all saved profile */
7279 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
7280 channels_allowed, &num_channels_allowed))
7281 {
7282 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7283 "%s: failed to get valid channel list", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307284 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307285 goto error;
7286 }
7287 /* Checking each channel against allowed channel list */
7288 num_ch = 0;
7289 for (i = 0; i < request->n_channels; i++)
7290 {
7291 for (indx = 0; indx < num_channels_allowed; indx++)
7292 {
7293 if (request->channels[i]->hw_value == channels_allowed[indx])
7294 {
7295 valid_ch[num_ch++] = request->channels[i]->hw_value;
7296 break ;
7297 }
7298 }
7299 }
7300
7301 /* Filling per profile params */
7302 for (i = 0; i < pPnoRequest->ucNetworksCount; i++)
7303 {
7304 pPnoRequest->aNetworks[i].ssId.length =
7305 request->match_sets[i].ssid.ssid_len;
7306
7307 if (( 0 == pPnoRequest->aNetworks[i].ssId.length ) ||
7308 ( pPnoRequest->aNetworks[i].ssId.length > 32 ) )
7309 {
7310 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7311 "SSID Len %d is not correct for network %d",
7312 pPnoRequest->aNetworks[i].ssId.length, i);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307313 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307314 goto error;
7315 }
7316
7317 memcpy(pPnoRequest->aNetworks[i].ssId.ssId,
7318 request->match_sets[i].ssid.ssid,
7319 request->match_sets[i].ssid.ssid_len);
7320 pPnoRequest->aNetworks[i].authentication = 0; /*eAUTH_TYPE_ANY*/
7321 pPnoRequest->aNetworks[i].encryption = 0; /*eED_ANY*/
7322 pPnoRequest->aNetworks[i].bcastNetwType = 0; /*eBCAST_UNKNOWN*/
7323
7324 /*Copying list of valid channel into request */
7325 memcpy(pPnoRequest->aNetworks[i].aChannels, valid_ch, num_ch);
7326 pPnoRequest->aNetworks[i].ucChannelCount = num_ch;
7327
7328 pPnoRequest->aNetworks[i].rssiThreshold = 0; //Default value
7329 }
7330
7331 /* framework provides interval in ms */
7332 pPnoRequest->scanTimers.ucScanTimersCount = 1;
7333 pPnoRequest->scanTimers.aTimerValues[0].uTimerValue =
7334 (request->interval)/1000;
7335 pPnoRequest->scanTimers.aTimerValues[0].uTimerRepeat = 0;
7336 pPnoRequest->modePNO = SIR_PNO_MODE_ON_SUSPEND;
7337
7338 status = sme_SetPreferredNetworkList(WLAN_HDD_GET_HAL_CTX(pAdapter),
7339 pPnoRequest, pAdapter->sessionId,
7340 hdd_cfg80211_sched_scan_done_callback, pAdapter);
7341 if (eHAL_STATUS_SUCCESS != status)
7342 {
7343 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7344 "Failed to enable PNO");
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307345 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307346 goto error;
7347 }
7348
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307349 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7350 "PNO scanRequest offloaded");
7351
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307352error:
7353 vos_mem_free(pPnoRequest);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307354 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307355}
7356
7357/*
7358 * FUNCTION: wlan_hdd_cfg80211_sched_scan_stop
7359 * NL interface to disable PNO
7360 */
7361static int wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy,
7362 struct net_device *dev)
7363{
7364 eHalStatus status = eHAL_STATUS_FAILURE;
7365 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7366 hdd_context_t *pHddCtx;
7367 tHalHandle hHal;
7368 tpSirPNOScanReq pPnoRequest = NULL;
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307369 int ret = 0;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307370
7371 ENTER();
7372
7373 if (NULL == pAdapter)
7374 {
7375 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7376 "%s: HDD adapter is Null", __func__);
7377 return -ENODEV;
7378 }
7379
7380 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307381
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307382 if (NULL == pHddCtx)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307383 {
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05307384 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307385 "%s: HDD context is Null", __func__);
7386 return -ENODEV;
7387 }
7388
7389 /* The return 0 is intentional when isLogpInProgress and
7390 * isLoadUnloadInProgress. We did observe a crash due to a return of
7391 * failure in sched_scan_stop , especially for a case where the unload
7392 * of the happens at the same time. The function __cfg80211_stop_sched_scan
7393 * was clearing rdev->sched_scan_req only when the sched_scan_stop returns
7394 * success. If it returns a failure , then its next invocation due to the
7395 * clean up of the second interface will have the dev pointer corresponding
7396 * to the first one leading to a crash.
7397 */
7398 if (pHddCtx->isLogpInProgress)
7399 {
7400 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7401 "%s: LOGP in Progress. Ignore!!!", __func__);
7402 return ret;
7403 }
7404
7405 if (pHddCtx->isLoadUnloadInProgress)
7406 {
7407 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7408 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
7409 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307410 }
7411
7412 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
7413 if (NULL == hHal)
7414 {
7415 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7416 "%s: HAL context is Null!!!", __func__);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307417 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307418 }
7419
7420 pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq));
7421 if (NULL == pPnoRequest)
7422 {
7423 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7424 "%s: vos_mem_malloc failed", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307425 return -ENOMEM;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307426 }
7427
7428 memset(pPnoRequest, 0, sizeof (tSirPNOScanReq));
7429 pPnoRequest->enable = 0; /* Disable PNO */
7430 pPnoRequest->ucNetworksCount = 0;
7431
7432 status = sme_SetPreferredNetworkList(hHal, pPnoRequest,
7433 pAdapter->sessionId,
7434 NULL, pAdapter);
7435 if (eHAL_STATUS_SUCCESS != status)
7436 {
7437 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7438 "Failed to disabled PNO");
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307439 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307440 }
7441
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307442 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7443 "%s: PNO scan disabled", __func__);
7444
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307445 vos_mem_free(pPnoRequest);
7446
7447 EXIT();
Kamath Vinayakba5313f2013-08-22 15:52:39 +05307448 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05307449}
7450
7451#endif /*FEATURE_WLAN_SCAN_PNO*/
7452
7453
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007454#ifdef FEATURE_WLAN_TDLS
7455static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
7456 u8 *peer, u8 action_code, u8 dialog_token,
7457 u16 status_code, const u8 *buf, size_t len)
7458{
7459
7460 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7461 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007462 u8 peerMac[6];
7463 VOS_STATUS status;
Gopichand Nakkala05922802013-03-14 12:23:19 -07007464 int max_sta_failed = 0;
Hoonki Leea34dd892013-02-05 22:56:02 -08007465 int responder;
Hoonki Leed37cbb32013-04-20 00:31:14 -07007466 long rc;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007467
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007468 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007469 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307470 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007471 "Invalid arguments");
7472 return -EINVAL;
7473 }
7474
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08007475 if (pHddCtx->isLogpInProgress)
7476 {
7477 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7478 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07007479 wlan_hdd_tdls_set_link_status(pAdapter, peer, eTDLS_LINK_IDLE);
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08007480 return -EBUSY;
7481 }
7482
Hoonki Lee27511902013-03-14 18:19:06 -07007483 if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007484 {
Hoonki Lee27511902013-03-14 18:19:06 -07007485 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
7486 "%s: TDLS mode is disabled OR not enabled in FW."
7487 MAC_ADDRESS_STR " action %d declined.",
7488 __func__, MAC_ADDR_ARRAY(peer), action_code);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007489 return -ENOTSUPP;
7490 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08007491
Hoonki Lee27511902013-03-14 18:19:06 -07007492 /* other than teardown frame, other mgmt frames are not sent if disabled */
7493 if (SIR_MAC_TDLS_TEARDOWN != action_code)
7494 {
7495 /* if tdls_mode is disabled to respond to peer's request */
7496 if (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode)
7497 {
7498 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
7499 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07007500 " TDLS mode is disabled. action %d declined.",
7501 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee27511902013-03-14 18:19:06 -07007502
7503 return -ENOTSUPP;
7504 }
7505 }
7506
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007507 if (WLAN_IS_TDLS_SETUP_ACTION(action_code))
7508 {
Hoonki Leefb8df672013-04-10 18:20:34 -07007509 if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, peer, TRUE, TRUE))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007510 {
7511 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007512 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07007513 " TDLS setup is ongoing. action %d declined.",
7514 __func__, MAC_ADDR_ARRAY(peer), action_code);
7515 return -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007516 }
7517 }
7518
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007519 if (SIR_MAC_TDLS_SETUP_REQ == action_code ||
7520 SIR_MAC_TDLS_SETUP_RSP == action_code )
Lee Hoonkic1262f22013-01-24 21:59:00 -08007521 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007522 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
Lee Hoonkic1262f22013-01-24 21:59:00 -08007523 {
7524 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
7525 we return error code at 'add_station()'. Hence we have this
7526 check again in addtion to add_station().
7527 Anyway, there is no hard to double-check. */
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007528 if (SIR_MAC_TDLS_SETUP_REQ == action_code)
Lee Hoonkic1262f22013-01-24 21:59:00 -08007529 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007530 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7531 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07007532 " TDLS Max peer already connected. action %d declined.",
7533 __func__, MAC_ADDR_ARRAY(peer), action_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07007534 goto error;
Lee Hoonkic1262f22013-01-24 21:59:00 -08007535 }
7536 else
7537 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007538 /* maximum reached. tweak to send error code to peer and return
7539 error code to supplicant */
Lee Hoonkic1262f22013-01-24 21:59:00 -08007540 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007541 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7542 "%s: " MAC_ADDRESS_STR
7543 " TDLS Max peer already connected send response status %d",
7544 __func__, MAC_ADDR_ARRAY(peer), status_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07007545 max_sta_failed = -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007546 /* fall through to send setup resp with failure status
7547 code */
Lee Hoonkic1262f22013-01-24 21:59:00 -08007548 }
7549 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007550 else
7551 {
7552 hddTdlsPeer_t *pTdlsPeer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007553 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007554 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007555 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007556 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07007557 "%s:" MAC_ADDRESS_STR " already connected. action %d declined.",
7558 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007559 return -EPERM;
7560 }
7561 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08007562 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007563 vos_mem_copy(peerMac, peer, 6);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007564
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007565#ifdef WLAN_FEATURE_TDLS_DEBUG
7566 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007567 "%s: " MAC_ADDRESS_STR " action %d, dialog_token %d status %d, len = %d",
7568 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
7569 action_code, dialog_token, status_code, len);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007570#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007571
Hoonki Leea34dd892013-02-05 22:56:02 -08007572 /*Except teardown responder will not be used so just make 0*/
7573 responder = 0;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007574 if (SIR_MAC_TDLS_TEARDOWN == action_code)
Hoonki Leea34dd892013-02-05 22:56:02 -08007575 {
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -07007576
7577 hddTdlsPeer_t *pTdlsPeer;
7578 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peerMac);
7579
7580 if(pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
7581 responder = pTdlsPeer->is_responder;
7582 else
Hoonki Leea34dd892013-02-05 22:56:02 -08007583 {
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -07007584 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7585 "%s: " MAC_ADDRESS_STR " peer doesn't exist or not connected %d dialog_token %d status %d, len = %d",
7586 __func__, MAC_ADDR_ARRAY(peer), (NULL == pTdlsPeer) ? -1 : pTdlsPeer->link_status,
7587 dialog_token, status_code, len);
7588 return -EPERM;
Hoonki Leea34dd892013-02-05 22:56:02 -08007589 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007590 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007591
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05307592 /* For explicit trigger of DIS_REQ come out of BMPS for
7593 successfully receiving DIS_RSP from peer. */
Hoonki Lee14621352013-04-16 17:51:19 -07007594 if ((SIR_MAC_TDLS_SETUP_RSP == action_code) ||
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05307595 (SIR_MAC_TDLS_DIS_RSP == action_code) ||
7596 (SIR_MAC_TDLS_DIS_REQ == action_code))
Hoonki Lee14621352013-04-16 17:51:19 -07007597 {
7598 if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter)))
7599 {
7600 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05307601 "%s: Sending frame action_code %u.Disable BMPS", __func__, action_code);
Hoonki Lee14621352013-04-16 17:51:19 -07007602 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
7603 }
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05307604 if (SIR_MAC_TDLS_DIS_REQ != action_code)
7605 wlan_hdd_tdls_set_cap(pAdapter, peerMac, eTDLS_CAP_SUPPORTED);
Hoonki Lee14621352013-04-16 17:51:19 -07007606 }
7607
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007608 /* make sure doesn't call send_mgmt() while it is pending */
7609 if (TDLS_CTX_MAGIC == pAdapter->mgmtTxCompletionStatus)
7610 {
7611 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7612 "%s: " MAC_ADDRESS_STR " action %d couldn't sent, as one is pending. return EBUSY\n",
7613 __func__, MAC_ADDR_ARRAY(peer), action_code);
7614 return -EBUSY;
7615 }
7616
7617 pAdapter->mgmtTxCompletionStatus = TDLS_CTX_MAGIC;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007618 INIT_COMPLETION(pAdapter->tdls_mgmt_comp);
7619
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007620 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
Hoonki Leea34dd892013-02-05 22:56:02 -08007621 peerMac, action_code, dialog_token, status_code, (tANI_U8 *)buf, len, responder);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007622
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007623 if (VOS_STATUS_SUCCESS != status)
7624 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007625 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7626 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007627 pAdapter->mgmtTxCompletionStatus = FALSE;
Hoonki Lee14621352013-04-16 17:51:19 -07007628 wlan_hdd_tdls_check_bmps(pAdapter);
7629 goto error;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007630 }
7631
Hoonki Leed37cbb32013-04-20 00:31:14 -07007632 rc = wait_for_completion_interruptible_timeout(&pAdapter->tdls_mgmt_comp,
7633 msecs_to_jiffies(WAIT_TIME_TDLS_MGMT));
7634
7635 if ((rc <= 0) || (TRUE != pAdapter->mgmtTxCompletionStatus))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007636 {
Hoonki Leed37cbb32013-04-20 00:31:14 -07007637 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7638 "%s: Mgmt Tx Completion failed status %ld TxCompletion %lu",
7639 __func__, rc, pAdapter->mgmtTxCompletionStatus);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007640 pAdapter->mgmtTxCompletionStatus = FALSE;
Hoonki Leed37cbb32013-04-20 00:31:14 -07007641 wlan_hdd_tdls_check_bmps(pAdapter);
7642 goto error;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007643 }
7644
Gopichand Nakkala05922802013-03-14 12:23:19 -07007645 if (max_sta_failed)
Hoonki Lee14621352013-04-16 17:51:19 -07007646 {
7647 wlan_hdd_tdls_check_bmps(pAdapter);
Gopichand Nakkala05922802013-03-14 12:23:19 -07007648 return max_sta_failed;
Hoonki Lee14621352013-04-16 17:51:19 -07007649 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007650
Hoonki Leea34dd892013-02-05 22:56:02 -08007651 if (SIR_MAC_TDLS_SETUP_RSP == action_code)
7652 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007653 wlan_hdd_tdls_set_responder(pAdapter, peerMac, TRUE);
Hoonki Leea34dd892013-02-05 22:56:02 -08007654 }
7655 else if (SIR_MAC_TDLS_SETUP_CNF == action_code)
7656 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007657 wlan_hdd_tdls_set_responder(pAdapter, peerMac, FALSE);
Hoonki Leea34dd892013-02-05 22:56:02 -08007658 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007659
7660 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07007661error:
7662 /* max_sta_failed ; we didn't set to CONNECTING for this case,
7663 because we already know that this transaction will be failed,
7664 but we weren't sure if supplicant call DISABLE_LINK or not. So,
7665 to be safe, do not change the state mahine.
7666 */
7667 if(max_sta_failed == 0 &&
7668 (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
7669 wlan_hdd_tdls_set_link_status(pAdapter, peerMac, eTDLS_LINK_IDLE);
7670 return -EPERM;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007671}
7672
7673static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
7674 u8 *peer, enum nl80211_tdls_operation oper)
7675{
7676 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7677 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307678 int status;
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05307679#ifdef FEATURE_WLAN_TDLS_OXYGEN_DISAPPEAR_AP
7680 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05307681 tANI_U8 staIdx;
7682#endif
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007683#ifdef WLAN_FEATURE_TDLS_DEBUG
7684 const char *tdls_oper_str[]= {
7685 "NL80211_TDLS_DISCOVERY_REQ",
7686 "NL80211_TDLS_SETUP",
7687 "NL80211_TDLS_TEARDOWN",
7688 "NL80211_TDLS_ENABLE_LINK",
7689 "NL80211_TDLS_DISABLE_LINK",
Gopichand Nakkala29d00192013-06-20 19:03:52 +05307690 "NL80211_TDLS_UNKNOWN_OPER"};
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007691#endif
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007692 hddTdlsPeer_t *pTdlsPeer;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007693
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307694 if ( NULL == peer )
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007695 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007696 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Chilam Ngc4244af2013-04-01 15:37:32 -07007697 "%s: Invalid arguments", __func__);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007698 return -EINVAL;
7699 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007700
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307701 status = wlan_hdd_validate_context(pHddCtx);
7702
7703 if (0 != status)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08007704 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307705 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7706 "%s: HDD context is not valid", __func__);
7707 return status;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08007708 }
7709
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007710 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
7711
7712 if ( NULL == pTdlsPeer ) {
7713 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: " MAC_ADDRESS_STR " (oper %d) not exsting. ignored",
7714 __func__, MAC_ADDR_ARRAY(peer), (int)oper);
7715 return -EINVAL;
7716 }
7717
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007718#ifdef WLAN_FEATURE_TDLS_DEBUG
7719 if((int)oper > 4)
7720 oper = 5;
7721
7722 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007723 "%s: " MAC_ADDRESS_STR " link_status %d (%s) ", "tdls_oper",
7724 MAC_ADDR_ARRAY(peer), pTdlsPeer->link_status,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007725 tdls_oper_str[(int)oper]);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007726#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007727
7728 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007729 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007730 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08007731 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Chilam Ngc4244af2013-04-01 15:37:32 -07007732 "TDLS Disabled in INI OR not enabled in FW. "
7733 "Cannot process TDLS commands");
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007734 return -ENOTSUPP;
7735 }
7736
7737 switch (oper) {
7738 case NL80211_TDLS_ENABLE_LINK:
7739 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007740 VOS_STATUS status;
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307741 tCsrTdlsLinkEstablishParams tdlsLinkEstablishParams;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007742
Gopichand Nakkala2f4a2822013-04-17 11:22:01 -07007743 if (!TDLS_STA_INDEX_VALID(pTdlsPeer->staId))
7744 {
7745 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Staion Index %u "
7746 MAC_ADDRESS_STR " failed",
7747 __func__, pTdlsPeer->staId, MAC_ADDR_ARRAY(peer));
7748 return -EINVAL;
7749 }
7750
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007751 if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status)
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007752 {
Gopichand Nakkala24be5312013-07-02 16:47:12 +05307753 long ret;
7754
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307755 if (0 != wlan_hdd_tdls_get_link_establish_params(pAdapter, peer,&tdlsLinkEstablishParams)) {
7756 return -EINVAL;
7757 }
7758 INIT_COMPLETION(pAdapter->tdls_link_establish_req_comp);
7759
7760 sme_SendTdlsLinkEstablishParams(WLAN_HDD_GET_HAL_CTX(pAdapter),
7761 pAdapter->sessionId, peer, &tdlsLinkEstablishParams);
7762 /* Send TDLS peer UAPSD capabilities to the firmware and
7763 * register with the TL on after the response for this operation
7764 * is received .
7765 */
Gopichand Nakkala24be5312013-07-02 16:47:12 +05307766 ret = wait_for_completion_interruptible_timeout(&pAdapter->tdls_link_establish_req_comp,
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307767 msecs_to_jiffies(WAIT_TIME_TDLS_LINK_ESTABLISH_REQ));
Gopichand Nakkala24be5312013-07-02 16:47:12 +05307768 if (ret <= 0)
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307769 {
7770 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7771 "%s: Link Establish Request Faled Status %ld",
Gopichand Nakkala24be5312013-07-02 16:47:12 +05307772 __func__, ret);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307773 return -EINVAL;
7774 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007775 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
Gopichand Nakkala471708b2013-06-04 20:03:01 +05307776 /* Mark TDLS client Authenticated .*/
7777 status = WLANTL_ChangeSTAState( pHddCtx->pvosContext,
7778 pTdlsPeer->staId,
7779 WLANTL_STA_AUTHENTICATED);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007780 if (VOS_STATUS_SUCCESS == status)
7781 {
Hoonki Lee14621352013-04-16 17:51:19 -07007782 if (pTdlsPeer->is_responder == 0)
7783 {
7784 v_U8_t staId = (v_U8_t)pTdlsPeer->staId;
7785
7786 wlan_hdd_tdls_timer_restart(pAdapter,
7787 &pTdlsPeer->initiatorWaitTimeoutTimer,
7788 WAIT_TIME_TDLS_INITIATOR);
7789 /* suspend initiator TX until it receives direct packet from the
7790 reponder or WAIT_TIME_TDLS_INITIATOR timer expires */
7791 WLANTL_SuspendDataTx( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
7792 &staId, NULL);
7793 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007794 wlan_hdd_tdls_increment_peer_count(pAdapter);
7795 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007796 wlan_hdd_tdls_check_bmps(pAdapter);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307797
7798 /* Update TL about the UAPSD masks , to route the packets to firmware */
Gopichand Nakkala574f6d12013-06-27 19:38:43 +05307799 if ((TRUE == pHddCtx->cfg_ini->fEnableTDLSBufferSta)
7800 || pHddCtx->cfg_ini->fTDLSUapsdMask )
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307801 {
Gopichand Nakkala574f6d12013-06-27 19:38:43 +05307802 int ac;
7803 uint8 ucAc[4] = { WLANTL_AC_VO,
7804 WLANTL_AC_VI,
7805 WLANTL_AC_BK,
7806 WLANTL_AC_BE };
7807 uint8 tlTid[4] = { 7, 5, 2, 3 } ;
7808 for(ac=0; ac < 4; ac++)
7809 {
7810 status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
7811 pTdlsPeer->staId, ucAc[ac],
7812 tlTid[ac], tlTid[ac], 0, 0,
7813 WLANTL_BI_DIR );
7814 }
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307815 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007816 }
7817
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007818 }
7819 break;
7820 case NL80211_TDLS_DISABLE_LINK:
Lee Hoonkic1262f22013-01-24 21:59:00 -08007821 {
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007822 if(TDLS_STA_INDEX_VALID(pTdlsPeer->staId))
Lee Hoonkic1262f22013-01-24 21:59:00 -08007823 {
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007824 long status;
7825
7826 INIT_COMPLETION(pAdapter->tdls_del_station_comp);
7827
Lee Hoonkic1262f22013-01-24 21:59:00 -08007828 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
7829 pAdapter->sessionId, peer );
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007830
7831 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_del_station_comp,
7832 msecs_to_jiffies(WAIT_TIME_TDLS_DEL_STA));
7833 if (status <= 0)
7834 {
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007835 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_IDLE);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007836 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7837 "%s: Del station failed status %ld",
7838 __func__, status);
7839 return -EPERM;
7840 }
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007841 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_IDLE);
Lee Hoonkic1262f22013-01-24 21:59:00 -08007842 }
7843 else
7844 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007845 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7846 "%s: TDLS Peer Station doesn't exist.", __func__);
Lee Hoonkic1262f22013-01-24 21:59:00 -08007847 }
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05307848#ifdef FEATURE_WLAN_TDLS_OXYGEN_DISAPPEAR_AP
7849 if (pHddTdlsCtx->defer_link_lost_indication)
7850 {
7851 if (( TRUE == pHddCtx->cfg_ini->fEnableTDLSOxygenSupport ) &&
7852 (wlan_hdd_tdlsConnectedPeers(pAdapter) == 0))
7853 {
7854 status = wlan_hdd_disconnect(pAdapter, eCSR_DISCONNECT_REASON_UNSPECIFIED);
7855 if ( 0 != status)
7856 {
7857 hddLog(VOS_TRACE_LEVEL_ERROR,
7858 "%s wlan_hdd_disconnect failure, returned %d \n",
7859 __func__, (int)status );
7860 return -EINVAL;
7861 }
7862 }
7863 }
7864#endif
Lee Hoonkic1262f22013-01-24 21:59:00 -08007865 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007866 break;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007867 case NL80211_TDLS_TEARDOWN:
7868 case NL80211_TDLS_SETUP:
7869 case NL80211_TDLS_DISCOVERY_REQ:
7870 /* We don't support in-driver setup/teardown/discovery */
7871 return -ENOTSUPP;
7872 default:
7873 return -ENOTSUPP;
7874 }
7875 return 0;
7876}
Chilam NG571c65a2013-01-19 12:27:36 +05307877
7878int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
7879 struct net_device *dev, u8 *peer)
7880{
7881 hddLog(VOS_TRACE_LEVEL_INFO, "tdls send discover req: %x %x %x %x %x %x",
7882 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5]);
7883
7884 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
7885 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
7886}
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007887#endif
7888
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05307889#ifdef WLAN_FEATURE_GTK_OFFLOAD
7890/*
7891 * FUNCTION: wlan_hdd_cfg80211_update_replayCounterCallback
7892 * Callback rountine called upon receiving response for
7893 * get offload info
7894 */
7895void wlan_hdd_cfg80211_update_replayCounterCallback(void *callbackContext,
7896 tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoRsp)
7897{
7898
7899 hdd_adapter_t *pAdapter = (hdd_adapter_t *)callbackContext;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05307900 tANI_U8 tempReplayCounter[8];
7901 hdd_station_ctx_t *pHddStaCtx;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05307902
7903 ENTER();
7904
7905 if (NULL == pAdapter)
7906 {
7907 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7908 "%s: HDD adapter is Null", __func__);
7909 return ;
7910 }
7911
7912 if (NULL == pGtkOffloadGetInfoRsp)
7913 {
7914 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7915 "%s: pGtkOffloadGetInfoRsp is Null", __func__);
7916 return ;
7917 }
7918
7919 if (VOS_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus)
7920 {
7921 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7922 "%s: wlan Failed to get replay counter value",
7923 __func__);
7924 return ;
7925 }
7926
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05307927 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7928 /* Update replay counter */
7929 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
7930 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
7931
7932 {
7933 /* changing from little to big endian since supplicant
7934 * works on big endian format
7935 */
7936 int i;
7937 tANI_U8 *p = (tANI_U8 *)&pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
7938
7939 for (i = 0; i < 8; i++)
7940 {
7941 tempReplayCounter[7-i] = (tANI_U8)p[i];
7942 }
7943 }
7944
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05307945 /* Update replay counter to NL */
7946 cfg80211_gtk_rekey_notify(pAdapter->dev, pGtkOffloadGetInfoRsp->bssId,
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05307947 tempReplayCounter, GFP_KERNEL);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05307948}
7949
7950/*
7951 * FUNCTION: wlan_hdd_cfg80211_set_rekey_data
7952 * This function is used to offload GTK rekeying job to the firmware.
7953 */
7954int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
7955 struct cfg80211_gtk_rekey_data *data)
7956{
7957 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7958 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
7959 hdd_station_ctx_t *pHddStaCtx;
7960 tHalHandle hHal;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307961 int result;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05307962 tSirGtkOffloadParams hddGtkOffloadReqParams;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05307963 eHalStatus status = eHAL_STATUS_FAILURE;
7964
7965 ENTER();
7966
7967 if (NULL == pAdapter)
7968 {
7969 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7970 "%s: HDD adapter is Null", __func__);
7971 return -ENODEV;
7972 }
7973
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307974 result = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05307975
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307976 if (0 != result)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05307977 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307978 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7979 "%s: HDD context is not valid", __func__);
7980 return result;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05307981 }
7982
7983 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7984 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
7985 if (NULL == hHal)
7986 {
7987 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7988 "%s: HAL context is Null!!!", __func__);
7989 return -EAGAIN;
7990 }
7991
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05307992 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
7993 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck, NL80211_KCK_LEN);
7994 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek, NL80211_KEK_LEN);
7995 memcpy(pHddStaCtx->gtkOffloadReqParams.bssId, &pHddStaCtx->conn_info.bssId,
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05307996 WNI_CFG_BSSID_LEN);
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05307997 {
7998 /* changing from big to little endian since driver
7999 * works on little endian format
8000 */
8001 tANI_U8 *p =
8002 (tANI_U8 *)&pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter;
8003 int i;
8004
8005 for (i = 0; i < 8; i++)
8006 {
8007 p[7-i] = data->replay_ctr[i];
8008 }
8009 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308010
8011 if (TRUE == pHddCtx->hdd_wlan_suspended)
8012 {
8013 /* if wlan is suspended, enable GTK offload directly from here */
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308014 memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams,
8015 sizeof (tSirGtkOffloadParams));
8016 status = sme_SetGTKOffload(hHal, &hddGtkOffloadReqParams,
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308017 pAdapter->sessionId);
8018
8019 if (eHAL_STATUS_SUCCESS != status)
8020 {
8021 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8022 "%s: sme_SetGTKOffload failed, returned %d",
8023 __func__, status);
8024 return status;
8025 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308026 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8027 "%s: sme_SetGTKOffload successfull", __func__);
8028 }
8029 else
8030 {
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308031 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8032 "%s: wlan not suspended GTKOffload request is stored",
8033 __func__);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308034 }
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308035
8036 return eHAL_STATUS_SUCCESS;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308037}
8038#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
8039
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05308040/*
8041 * FUNCTION: wlan_hdd_cfg80211_set_mac_acl
8042 * This function is used to set access control policy
8043 */
8044static int wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
8045 struct net_device *dev, const struct cfg80211_acl_data *params)
8046{
8047 int i;
8048 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8049 hdd_hostapd_state_t *pHostapdState;
8050 tsap_Config_t *pConfig;
8051 v_CONTEXT_t pVosContext = NULL;
8052 hdd_context_t *pHddCtx;
8053 int status;
8054
8055 ENTER();
8056
8057 if (NULL == pAdapter)
8058 {
8059 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8060 "%s: HDD adapter is Null", __func__);
8061 return -ENODEV;
8062 }
8063
8064 if (NULL == params)
8065 {
8066 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8067 "%s: params is Null", __func__);
8068 return -EINVAL;
8069 }
8070
8071 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8072 status = wlan_hdd_validate_context(pHddCtx);
8073
8074 if (0 != status)
8075 {
8076 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8077 "%s: HDD context is not valid", __func__);
8078 return status;
8079 }
8080
8081 pVosContext = pHddCtx->pvosContext;
8082 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
8083
8084 if (NULL == pHostapdState)
8085 {
8086 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8087 "%s: pHostapdState is Null", __func__);
8088 return -EINVAL;
8089 }
8090
8091 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"acl policy: = %d"
8092 "no acl entries = %d", params->acl_policy, params->n_acl_entries);
8093
8094 if (WLAN_HDD_SOFTAP == pAdapter->device_mode)
8095 {
8096 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
8097
8098 /* default value */
8099 pConfig->num_accept_mac = 0;
8100 pConfig->num_deny_mac = 0;
8101
8102 /**
8103 * access control policy
8104 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
8105 * listed in hostapd.deny file.
8106 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
8107 * listed in hostapd.accept file.
8108 */
8109 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy)
8110 {
8111 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
8112 }
8113 else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED == params->acl_policy)
8114 {
8115 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
8116 }
8117 else
8118 {
8119 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8120 "%s:Acl Policy : %d is not supported",
8121 __func__, params->acl_policy);
8122 return -ENOTSUPP;
8123 }
8124
8125 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl)
8126 {
8127 pConfig->num_accept_mac = params->n_acl_entries;
8128 for (i = 0; i < params->n_acl_entries; i++)
8129 {
8130 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8131 "** Add ACL MAC entry %i in WhiletList :"
8132 MAC_ADDRESS_STR, i,
8133 MAC_ADDR_ARRAY(params->mac_addrs[i].addr));
8134
8135 vos_mem_copy(&pConfig->accept_mac[i], params->mac_addrs[i].addr,
8136 sizeof(qcmacaddr));
8137 }
8138 }
8139 else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl)
8140 {
8141 pConfig->num_deny_mac = params->n_acl_entries;
8142 for (i = 0; i < params->n_acl_entries; i++)
8143 {
8144 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8145 "** Add ACL MAC entry %i in BlackList :"
8146 MAC_ADDRESS_STR, i,
8147 MAC_ADDR_ARRAY(params->mac_addrs[i].addr));
8148
8149 vos_mem_copy(&pConfig->deny_mac[i], params->mac_addrs[i].addr,
8150 sizeof(qcmacaddr));
8151 }
8152 }
8153
8154 if (VOS_STATUS_SUCCESS != WLANSAP_SetMacACL(pVosContext, pConfig))
8155 {
8156 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8157 "%s: SAP Set Mac Acl fail", __func__);
8158 return -EINVAL;
8159 }
8160 }
8161 else
8162 {
8163 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8164 "%s: Invalid device_mode = %d",
8165 __func__, pAdapter->device_mode);
8166 return -EINVAL;
8167 }
8168
8169 return 0;
8170}
8171
Leo Chang9056f462013-08-01 19:21:11 -07008172#ifdef WLAN_NL80211_TESTMODE
8173#ifdef FEATURE_WLAN_LPHB
8174static void wlan_hdd_cfg80211_lphb_wait_timeout_ind_handler
8175(
8176 void *pAdapter,
8177 void *indCont
8178)
8179{
8180 tSirLPHBTimeoutInd *lphbTimeoutInd;
8181 struct sk_buff *skb;
8182
8183 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8184 "LPHB wait timeout indication arrived");
8185
8186 if (NULL == indCont)
8187 {
8188 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8189 "LPHB timeout, invalid argument");
8190 return;
8191 }
8192
8193 lphbTimeoutInd = (tSirLPHBTimeoutInd *)indCont;
8194 skb = cfg80211_testmode_alloc_event_skb(
8195 ((hdd_adapter_t *)pAdapter)->wdev.wiphy,
8196 sizeof(tSirLPHBTimeoutInd),
8197 GFP_ATOMIC);
8198 if (!skb)
8199 {
8200 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8201 "LPHB timeout, NL buffer alloc fail");
8202 return;
8203 }
8204
8205 NLA_PUT_U32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB);
8206 NLA_PUT_U32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbTimeoutInd->protocolType);
8207 NLA_PUT(skb, WLAN_HDD_TM_ATTR_DATA,
8208 sizeof(tSirLPHBTimeoutInd), lphbTimeoutInd);
8209 cfg80211_testmode_event(skb, GFP_ATOMIC);
8210 return;
8211
8212nla_put_failure:
8213 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8214 "NLA Put fail");
8215 kfree_skb(skb);
8216
8217 return;
8218}
8219#endif /* FEATURE_WLAN_LPHB */
8220
8221static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy, void *data, int len)
8222{
8223 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
8224 int err = 0;
8225#ifdef FEATURE_WLAN_LPHB
8226 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8227#endif /* FEATURE_WLAN_LPHB */
8228
8229 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data, len, wlan_hdd_tm_policy);
8230 if (err)
8231 {
8232 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8233 "%s Testmode INV ATTR", __func__);
8234 return err;
8235 }
8236
8237 if (!tb[WLAN_HDD_TM_ATTR_CMD])
8238 {
8239 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8240 "%s Testmode INV CMD", __func__);
8241 return -EINVAL;
8242 }
8243
8244 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]))
8245 {
8246#ifdef FEATURE_WLAN_LPHB
8247 /* Low Power Heartbeat configuration request */
8248 case WLAN_HDD_TM_CMD_WLAN_HB:
8249 {
8250 int buf_len;
8251 void *buf;
8252 tSirLPHBReq *hb_params = NULL;
8253
8254 if (!tb[WLAN_HDD_TM_ATTR_DATA])
8255 {
8256 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8257 "%s Testmode INV DATA", __func__);
8258 return -EINVAL;
8259 }
8260
8261 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
8262 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
8263 hb_params = (tSirLPHBReq *)vos_mem_malloc(sizeof(tSirLPHBReq));
8264 if (NULL == hb_params)
8265 {
8266 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8267 "%s Request Buffer Alloc Fail", __func__);
8268 return -EINVAL;
8269 }
8270
8271 vos_mem_copy(hb_params, buf, buf_len);
8272
8273 /* LPHB enable and disable request will send to FW
8274 * when host suspend and resume
8275 * host suspend -> enable LPHB
8276 * host resume -> disable LPHB
8277 * if host is not suspend, cache into HDD context
8278 * and when host goes to suspend, send request to FW */
8279 if ((LPHB_SET_EN_PARAMS_INDID == hb_params->cmd) &&
8280 (!pHddCtx->hdd_wlan_suspended))
8281 {
8282 /* Feature enable command cache into HDD context,
8283 * if WLAN is not suspend
8284 * When WLAN goes into suspend, send enable command to FW */
8285 pHddCtx->lphbEnableReq.enable =
8286 hb_params->params.lphbEnableReq.enable;
8287 pHddCtx->lphbEnableReq.item =
8288 hb_params->params.lphbEnableReq.item;
8289 pHddCtx->lphbEnableReq.session =
8290 hb_params->params.lphbEnableReq.session;
8291 vos_mem_free(hb_params);
8292 }
8293 else
8294 {
8295 eHalStatus smeStatus;
8296
8297 /* If WLAN is suspend state, send enable command immediately */
8298 smeStatus = sme_LPHBConfigReq((tHalHandle)(pHddCtx->hHal),
8299 hb_params,
8300 wlan_hdd_cfg80211_lphb_wait_timeout_ind_handler);
8301 if (eHAL_STATUS_SUCCESS != smeStatus)
8302 {
8303 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8304 "LPHB Config Fail, disable");
8305 pHddCtx->lphbEnableReq.enable = 0;
8306 vos_mem_free(hb_params);
8307 }
8308 }
8309 return 0;
8310 }
8311#endif /* FEATURE_WLAN_LPHB */
8312 default:
8313 return -EOPNOTSUPP;
8314 }
8315
8316 return err;
8317}
8318#endif /* CONFIG_NL80211_TESTMODE */
8319
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308320static int wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy,
8321 struct net_device *dev,
8322 int idx, struct survey_info *survey)
8323{
8324 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8325 hdd_context_t *pHddCtx;
8326 tHalHandle halHandle;
8327 v_U32_t channel, freq;
8328 v_S7_t snr,rssi;
8329 int status, i, j, filled = 0;
8330
8331 ENTER();
8332
8333
8334 if (NULL == pAdapter)
8335 {
8336 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8337 "%s: HDD adapter is Null", __func__);
8338 return -ENODEV;
8339 }
8340
8341 if (NULL == wiphy)
8342 {
8343 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8344 "%s: wiphy is Null", __func__);
8345 return -ENODEV;
8346 }
8347
8348 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8349 status = wlan_hdd_validate_context(pHddCtx);
8350
8351 if (0 != status)
8352 {
8353 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8354 "%s: HDD context is not valid", __func__);
8355 return status;
8356 }
8357
8358 if (0 == pHddCtx->cfg_ini->fEnableSNRMonitoring ||
8359 0 != pAdapter->survey_idx)
8360 {
8361 /* The survey dump ops when implemented completely is expected to
8362 * return a survey of all channels and the ops is called by the
8363 * kernel with incremental values of the argument 'idx' till it
8364 * returns -ENONET. But we can only support the survey for the
8365 * operating channel for now. survey_idx is used to track
8366 * that the ops is called only once and then return -ENONET for
8367 * the next iteration
8368 */
8369 pAdapter->survey_idx = 0;
8370 return -ENONET;
8371 }
8372
8373 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
8374
8375 wlan_hdd_get_snr(pAdapter, &snr);
8376 wlan_hdd_get_rssi(pAdapter, &rssi);
8377
8378 sme_GetOperationChannel(halHandle, &channel, pAdapter->sessionId);
8379 hdd_wlan_get_freq(channel, &freq);
8380
8381
8382 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
8383 {
8384 if (NULL == wiphy->bands[i])
8385 {
8386 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
8387 "%s: wiphy->bands[i] is NULL, i = %d", __func__, i);
8388 continue;
8389 }
8390
8391 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
8392 {
8393 struct ieee80211_supported_band *band = wiphy->bands[i];
8394
8395 if (band->channels[j].center_freq == (v_U16_t)freq)
8396 {
8397 survey->channel = &band->channels[j];
8398 /* The Rx BDs contain SNR values in dB for the received frames
8399 * while the supplicant expects noise. So we calculate and
8400 * return the value of noise (dBm)
8401 * SNR (dB) = RSSI (dBm) - NOISE (dBm)
8402 */
8403 survey->noise = rssi - snr;
8404 survey->filled = SURVEY_INFO_NOISE_DBM;
8405 filled = 1;
8406 }
8407 }
8408 }
8409
8410 if (filled)
8411 pAdapter->survey_idx = 1;
8412 else
8413 {
8414 pAdapter->survey_idx = 0;
8415 return -ENONET;
8416 }
8417
8418 return 0;
8419}
8420
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308421/*
8422 * FUNCTION: wlan_hdd_cfg80211_resume_wlan
8423 * this is called when cfg80211 driver resume
8424 * driver updates latest sched_scan scan result(if any) to cfg80211 database
8425 */
8426int wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
8427{
8428 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8429 hdd_adapter_t *pAdapter;
8430 hdd_adapter_list_node_t *pAdapterNode, *pNext;
8431 VOS_STATUS status = VOS_STATUS_SUCCESS;
8432
8433 ENTER();
8434
8435 if ( NULL == pHddCtx )
8436 {
8437 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8438 "%s: HddCtx validation failed", __func__);
8439 return 0;
8440 }
8441
8442 if (pHddCtx->isLogpInProgress)
8443 {
8444 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8445 "%s: LOGP in Progress. Ignore!!!", __func__);
8446 return 0;
8447 }
8448
8449 if (pHddCtx->isLoadUnloadInProgress)
8450 {
8451 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8452 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
8453 return 0;
8454 }
8455
8456 spin_lock(&pHddCtx->schedScan_lock);
8457 pHddCtx->isWiphySuspended = FALSE;
8458 if (TRUE != pHddCtx->isSchedScanUpdatePending)
8459 {
8460 spin_unlock(&pHddCtx->schedScan_lock);
8461 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8462 "%s: Return resume is not due to PNO indication", __func__);
8463 return 0;
8464 }
8465 // Reset flag to avoid updatating cfg80211 data old results again
8466 pHddCtx->isSchedScanUpdatePending = FALSE;
8467 spin_unlock(&pHddCtx->schedScan_lock);
8468
8469 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8470
8471 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
8472 {
8473 pAdapter = pAdapterNode->pAdapter;
8474 if ( (NULL != pAdapter) &&
8475 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
8476 {
8477 if (0 != wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter))
8478 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
8479 "%s: NO SCAN result", __func__);
8480 else
8481 cfg80211_sched_scan_results(pHddCtx->wiphy);
8482
8483 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8484 "%s : cfg80211 scan result database updated", __func__);
8485
8486 return 0;
8487
8488 }
8489 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8490 pAdapterNode = pNext;
8491 }
8492
8493 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8494 "%s: Failed to find Adapter", __func__);
8495 return 0;
8496}
8497
8498/*
8499 * FUNCTION: wlan_hdd_cfg80211_suspend_wlan
8500 * this is called when cfg80211 driver suspends
8501 */
8502int wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
8503 struct cfg80211_wowlan *wow)
8504{
8505 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8506
8507 ENTER();
8508 if (NULL == pHddCtx)
8509 {
8510 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8511 "%s: HddCtx validation failed", __func__);
8512 return 0;
8513 }
8514
8515 pHddCtx->isWiphySuspended = TRUE;
8516
8517 EXIT();
8518
8519 return 0;
8520}
8521
Jeff Johnson295189b2012-06-20 16:38:30 -07008522/* cfg80211_ops */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308523static struct cfg80211_ops wlan_hdd_cfg80211_ops =
Jeff Johnson295189b2012-06-20 16:38:30 -07008524{
8525 .add_virtual_intf = wlan_hdd_add_virtual_intf,
8526 .del_virtual_intf = wlan_hdd_del_virtual_intf,
8527 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
8528 .change_station = wlan_hdd_change_station,
8529#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
8530 .add_beacon = wlan_hdd_cfg80211_add_beacon,
8531 .del_beacon = wlan_hdd_cfg80211_del_beacon,
8532 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008533#else
8534 .start_ap = wlan_hdd_cfg80211_start_ap,
8535 .change_beacon = wlan_hdd_cfg80211_change_beacon,
8536 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07008537#endif
8538 .change_bss = wlan_hdd_cfg80211_change_bss,
8539 .add_key = wlan_hdd_cfg80211_add_key,
8540 .get_key = wlan_hdd_cfg80211_get_key,
8541 .del_key = wlan_hdd_cfg80211_del_key,
8542 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08008543#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07008544 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08008545#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008546 .scan = wlan_hdd_cfg80211_scan,
8547 .connect = wlan_hdd_cfg80211_connect,
8548 .disconnect = wlan_hdd_cfg80211_disconnect,
8549 .join_ibss = wlan_hdd_cfg80211_join_ibss,
8550 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
8551 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
8552 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
8553 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
Jeff Johnson295189b2012-06-20 16:38:30 -07008554 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
8555 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
8556 .mgmt_tx = wlan_hdd_action,
8557#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
8558 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
8559 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
8560 .set_txq_params = wlan_hdd_set_txq_params,
8561#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008562 .get_station = wlan_hdd_cfg80211_get_station,
8563 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
8564 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008565 .add_station = wlan_hdd_cfg80211_add_station,
8566#ifdef FEATURE_WLAN_LFR
8567 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
8568 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
8569 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
8570#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07008571#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
8572 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
8573#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008574#ifdef FEATURE_WLAN_TDLS
8575 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
8576 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
8577#endif
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308578#ifdef WLAN_FEATURE_GTK_OFFLOAD
8579 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
8580#endif /* WLAN_FEATURE_GTK_OFFLOAD */
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308581#ifdef FEATURE_WLAN_SCAN_PNO
8582 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
8583 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
8584#endif /*FEATURE_WLAN_SCAN_PNO */
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308585 .resume = wlan_hdd_cfg80211_resume_wlan,
8586 .suspend = wlan_hdd_cfg80211_suspend_wlan,
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05308587 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
Leo Chang9056f462013-08-01 19:21:11 -07008588#ifdef WLAN_NL80211_TESTMODE
8589 .testmode_cmd = wlan_hdd_cfg80211_testmode,
8590#endif
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308591 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Jeff Johnson295189b2012-06-20 16:38:30 -07008592};
8593