blob: bf7a0a73d23c0a1e7ad106c68571116e0df5de9b [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * 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 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/**========================================================================
43
44 \file wlan_hdd_cfg80211.c
45
46 \brief WLAN Host Device Driver implementation
47
48 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
49
50 Qualcomm Confidential and Proprietary.
51
52 ========================================================================*/
53
54/**=========================================================================
55
56 EDIT HISTORY FOR FILE
57
58
59 This section contains comments describing changes made to the module.
60 Notice that changes are listed in reverse chronological order.
61
62
63 $Header:$ $DateTime: $ $Author: $
64
65
66 when who what, where, why
67 -------- --- --------------------------------------------------------
68 21/12/09 Ashwani Created module.
69
70 07/06/10 Kumar Deepak Implemented cfg80211 callbacks for ANDROID
71 Ganesh K
72 ==========================================================================*/
73
Jeff Johnson295189b2012-06-20 16:38:30 -070074
75#include <linux/version.h>
76#include <linux/module.h>
77#include <linux/kernel.h>
78#include <linux/init.h>
79#include <linux/wireless.h>
80#include <wlan_hdd_includes.h>
81#include <net/arp.h>
82#include <net/cfg80211.h>
83#include <linux/wireless.h>
84#include <wlan_hdd_wowl.h>
85#include <aniGlobal.h>
86#include "ccmApi.h"
87#include "sirParams.h"
88#include "dot11f.h"
89#include "wlan_hdd_assoc.h"
90#include "wlan_hdd_wext.h"
91#include "sme_Api.h"
92#include "wlan_hdd_p2p.h"
93#include "wlan_hdd_cfg80211.h"
94#include "wlan_hdd_hostapd.h"
95#include "sapInternal.h"
96#include "wlan_hdd_softap_tx_rx.h"
97#include "wlan_hdd_main.h"
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +053098#include "wlan_hdd_assoc.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070099#ifdef WLAN_BTAMP_FEATURE
100#include "bap_hdd_misc.h"
101#endif
102#include <qc_sap_ioctl.h>
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800103#ifdef FEATURE_WLAN_TDLS
104#include "wlan_hdd_tdls.h"
105#endif
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +0530106#include "wlan_nv.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700107
108#define g_mode_rates_size (12)
109#define a_mode_rates_size (8)
110#define FREQ_BASE_80211G (2407)
111#define FREQ_BAND_DIFF_80211G (5)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700112#define MAX_SCAN_SSID 9
Jeff Johnson295189b2012-06-20 16:38:30 -0700113#define GET_IE_LEN_IN_BSS_DESC(lenInBss) ( lenInBss + sizeof(lenInBss) - \
114 ((int) OFFSET_OF( tSirBssDescription, ieFields)))
115
116#define HDD2GHZCHAN(freq, chan, flag) { \
117 .band = IEEE80211_BAND_2GHZ, \
118 .center_freq = (freq), \
119 .hw_value = (chan),\
120 .flags = (flag), \
121 .max_antenna_gain = 0 ,\
122 .max_power = 30, \
123}
124
125#define HDD5GHZCHAN(freq, chan, flag) { \
126 .band = IEEE80211_BAND_5GHZ, \
127 .center_freq = (freq), \
128 .hw_value = (chan),\
129 .flags = (flag), \
130 .max_antenna_gain = 0 ,\
131 .max_power = 30, \
132}
133
134#define HDD_G_MODE_RATETAB(rate, rate_id, flag)\
135{\
136 .bitrate = rate, \
137 .hw_value = rate_id, \
138 .flags = flag, \
139}
140
Lee Hoonkic1262f22013-01-24 21:59:00 -0800141#ifndef WLAN_FEATURE_TDLS_DEBUG
142#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_INFO
143#else
144#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_ERROR
145#endif
146
Jeff Johnson295189b2012-06-20 16:38:30 -0700147static const u32 hdd_cipher_suites[] =
148{
149 WLAN_CIPHER_SUITE_WEP40,
150 WLAN_CIPHER_SUITE_WEP104,
151 WLAN_CIPHER_SUITE_TKIP,
152#ifdef FEATURE_WLAN_CCX
153#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
154 WLAN_CIPHER_SUITE_KRK,
155 WLAN_CIPHER_SUITE_CCMP,
156#else
157 WLAN_CIPHER_SUITE_CCMP,
158#endif
159#ifdef FEATURE_WLAN_WAPI
160 WLAN_CIPHER_SUITE_SMS4,
161#endif
162};
163
164static inline int is_broadcast_ether_addr(const u8 *addr)
165{
166 return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&
167 (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
168}
169
170static struct ieee80211_channel hdd_channels_2_4_GHZ[] =
171{
172 HDD2GHZCHAN(2412, 1, 0) ,
173 HDD2GHZCHAN(2417, 2, 0) ,
174 HDD2GHZCHAN(2422, 3, 0) ,
175 HDD2GHZCHAN(2427, 4, 0) ,
176 HDD2GHZCHAN(2432, 5, 0) ,
177 HDD2GHZCHAN(2437, 6, 0) ,
178 HDD2GHZCHAN(2442, 7, 0) ,
179 HDD2GHZCHAN(2447, 8, 0) ,
180 HDD2GHZCHAN(2452, 9, 0) ,
181 HDD2GHZCHAN(2457, 10, 0) ,
182 HDD2GHZCHAN(2462, 11, 0) ,
183 HDD2GHZCHAN(2467, 12, 0) ,
184 HDD2GHZCHAN(2472, 13, 0) ,
185 HDD2GHZCHAN(2484, 14, 0) ,
186};
187
Jeff Johnson295189b2012-06-20 16:38:30 -0700188static struct ieee80211_channel hdd_social_channels_2_4_GHZ[] =
189{
190 HDD2GHZCHAN(2412, 1, 0) ,
191 HDD2GHZCHAN(2437, 6, 0) ,
192 HDD2GHZCHAN(2462, 11, 0) ,
193};
Jeff Johnson295189b2012-06-20 16:38:30 -0700194
195static struct ieee80211_channel hdd_channels_5_GHZ[] =
196{
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700197 HDD5GHZCHAN(4920, 240, 0) ,
198 HDD5GHZCHAN(4940, 244, 0) ,
199 HDD5GHZCHAN(4960, 248, 0) ,
200 HDD5GHZCHAN(4980, 252, 0) ,
201 HDD5GHZCHAN(5040, 208, 0) ,
202 HDD5GHZCHAN(5060, 212, 0) ,
203 HDD5GHZCHAN(5080, 216, 0) ,
Jeff Johnson295189b2012-06-20 16:38:30 -0700204 HDD5GHZCHAN(5180, 36, 0) ,
205 HDD5GHZCHAN(5200, 40, 0) ,
206 HDD5GHZCHAN(5220, 44, 0) ,
207 HDD5GHZCHAN(5240, 48, 0) ,
208 HDD5GHZCHAN(5260, 52, 0) ,
209 HDD5GHZCHAN(5280, 56, 0) ,
210 HDD5GHZCHAN(5300, 60, 0) ,
211 HDD5GHZCHAN(5320, 64, 0) ,
212 HDD5GHZCHAN(5500,100, 0) ,
213 HDD5GHZCHAN(5520,104, 0) ,
214 HDD5GHZCHAN(5540,108, 0) ,
215 HDD5GHZCHAN(5560,112, 0) ,
216 HDD5GHZCHAN(5580,116, 0) ,
217 HDD5GHZCHAN(5600,120, 0) ,
218 HDD5GHZCHAN(5620,124, 0) ,
219 HDD5GHZCHAN(5640,128, 0) ,
220 HDD5GHZCHAN(5660,132, 0) ,
221 HDD5GHZCHAN(5680,136, 0) ,
222 HDD5GHZCHAN(5700,140, 0) ,
223 HDD5GHZCHAN(5745,149, 0) ,
224 HDD5GHZCHAN(5765,153, 0) ,
225 HDD5GHZCHAN(5785,157, 0) ,
226 HDD5GHZCHAN(5805,161, 0) ,
227 HDD5GHZCHAN(5825,165, 0) ,
228};
229
230static struct ieee80211_rate g_mode_rates[] =
231{
232 HDD_G_MODE_RATETAB(10, 0x1, 0),
233 HDD_G_MODE_RATETAB(20, 0x2, 0),
234 HDD_G_MODE_RATETAB(55, 0x4, 0),
235 HDD_G_MODE_RATETAB(110, 0x8, 0),
236 HDD_G_MODE_RATETAB(60, 0x10, 0),
237 HDD_G_MODE_RATETAB(90, 0x20, 0),
238 HDD_G_MODE_RATETAB(120, 0x40, 0),
239 HDD_G_MODE_RATETAB(180, 0x80, 0),
240 HDD_G_MODE_RATETAB(240, 0x100, 0),
241 HDD_G_MODE_RATETAB(360, 0x200, 0),
242 HDD_G_MODE_RATETAB(480, 0x400, 0),
243 HDD_G_MODE_RATETAB(540, 0x800, 0),
244};
245
246static struct ieee80211_rate a_mode_rates[] =
247{
248 HDD_G_MODE_RATETAB(60, 0x10, 0),
249 HDD_G_MODE_RATETAB(90, 0x20, 0),
250 HDD_G_MODE_RATETAB(120, 0x40, 0),
251 HDD_G_MODE_RATETAB(180, 0x80, 0),
252 HDD_G_MODE_RATETAB(240, 0x100, 0),
253 HDD_G_MODE_RATETAB(360, 0x200, 0),
254 HDD_G_MODE_RATETAB(480, 0x400, 0),
255 HDD_G_MODE_RATETAB(540, 0x800, 0),
256};
257
258static struct ieee80211_supported_band wlan_hdd_band_2_4_GHZ =
259{
260 .channels = hdd_channels_2_4_GHZ,
261 .n_channels = ARRAY_SIZE(hdd_channels_2_4_GHZ),
262 .band = IEEE80211_BAND_2GHZ,
263 .bitrates = g_mode_rates,
264 .n_bitrates = g_mode_rates_size,
265 .ht_cap.ht_supported = 1,
266 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
267 | IEEE80211_HT_CAP_GRN_FLD
268 | IEEE80211_HT_CAP_DSSSCCK40
269 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
270 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
271 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
272 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
273 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
274 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
275};
276
Jeff Johnson295189b2012-06-20 16:38:30 -0700277static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_GHZ =
278{
279 .channels = hdd_social_channels_2_4_GHZ,
280 .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_GHZ),
281 .band = IEEE80211_BAND_2GHZ,
282 .bitrates = g_mode_rates,
283 .n_bitrates = g_mode_rates_size,
284 .ht_cap.ht_supported = 1,
285 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
286 | IEEE80211_HT_CAP_GRN_FLD
287 | IEEE80211_HT_CAP_DSSSCCK40
288 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
289 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
290 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
291 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
292 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
293 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
294};
Jeff Johnson295189b2012-06-20 16:38:30 -0700295
296static struct ieee80211_supported_band wlan_hdd_band_5_GHZ =
297{
298 .channels = hdd_channels_5_GHZ,
299 .n_channels = ARRAY_SIZE(hdd_channels_5_GHZ),
300 .band = IEEE80211_BAND_5GHZ,
301 .bitrates = a_mode_rates,
302 .n_bitrates = a_mode_rates_size,
303 .ht_cap.ht_supported = 1,
304 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
305 | IEEE80211_HT_CAP_GRN_FLD
306 | IEEE80211_HT_CAP_DSSSCCK40
307 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
308 | IEEE80211_HT_CAP_SGI_40
309 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
310 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
311 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
312 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
313 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
314 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
315};
316
317/* This structure contain information what kind of frame are expected in
318 TX/RX direction for each kind of interface */
319static const struct ieee80211_txrx_stypes
320wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
321 [NL80211_IFTYPE_STATION] = {
322 .tx = 0xffff,
323 .rx = BIT(SIR_MAC_MGMT_ACTION) |
324 BIT(SIR_MAC_MGMT_PROBE_REQ),
325 },
326 [NL80211_IFTYPE_AP] = {
327 .tx = 0xffff,
328 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
329 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
330 BIT(SIR_MAC_MGMT_PROBE_REQ) |
331 BIT(SIR_MAC_MGMT_DISASSOC) |
332 BIT(SIR_MAC_MGMT_AUTH) |
333 BIT(SIR_MAC_MGMT_DEAUTH) |
334 BIT(SIR_MAC_MGMT_ACTION),
335 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700336 [NL80211_IFTYPE_P2P_CLIENT] = {
337 .tx = 0xffff,
338 .rx = BIT(SIR_MAC_MGMT_ACTION) |
339 BIT(SIR_MAC_MGMT_PROBE_REQ),
340 },
341 [NL80211_IFTYPE_P2P_GO] = {
342 /* This is also same as for SoftAP */
343 .tx = 0xffff,
344 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
345 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
346 BIT(SIR_MAC_MGMT_PROBE_REQ) |
347 BIT(SIR_MAC_MGMT_DISASSOC) |
348 BIT(SIR_MAC_MGMT_AUTH) |
349 BIT(SIR_MAC_MGMT_DEAUTH) |
350 BIT(SIR_MAC_MGMT_ACTION),
351 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700352};
353
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800354#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800355static const struct ieee80211_iface_limit
356wlan_hdd_iface_limit[] = {
357 {
Sunil Ravia72c3992013-01-31 06:12:22 -0800358 /* max = 3 ; Our driver create two interfaces during driver init
359 * wlan0 and p2p0 interfaces. p2p0 is considered as station
360 * interface until a group is formed. In JB architecture, once the
361 * group is formed, interface type of p2p0 is changed to P2P GO or
362 * Client.
363 * When supplicant remove the group, it first issue a set interface
364 * cmd to change the mode back to Station. In JB this works fine as
365 * we advertize two station type interface during driver init.
366 * Some vendors create separate interface for P2P GO/Client,
367 * after group formation(Third one). But while group remove
368 * supplicant first tries to change the mode(3rd interface) to STATION
369 * But as we advertized only two sta type interfaces nl80211 was
370 * returning error for the third one which was leading to failure in
371 * delete interface. Ideally while removing the group, supplicant
372 * should not try to change the 3rd interface mode to Station type.
373 * Till we get a fix in wpa_supplicant, we advertize max STA
374 * interface type to 3
375 */
376 .max = 3,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800377 .types = BIT(NL80211_IFTYPE_STATION),
378 },
379 {
380 .max = 1,
381 .types = BIT(NL80211_IFTYPE_AP),
382 },
383 {
384 .max = 1,
385 .types = BIT(NL80211_IFTYPE_P2P_GO) |
386 BIT(NL80211_IFTYPE_P2P_CLIENT),
387 },
388};
389
390/* By default, only single channel concurrency is allowed */
391static struct ieee80211_iface_combination
392wlan_hdd_iface_combination = {
393 .limits = wlan_hdd_iface_limit,
394 .num_different_channels = 1,
Sunil Ravia72c3992013-01-31 06:12:22 -0800395 /*
396 * max = WLAN_MAX_INTERFACES ; JellyBean architecture creates wlan0
397 * and p2p0 interfaces during driver init
398 * Some vendors create separate interface for P2P operations.
399 * wlan0: STA interface
400 * p2p0: P2P Device interface, action frames goes
401 * through this interface.
402 * p2p-xx: P2P interface, After GO negotiation this interface is
403 * created for p2p operations(GO/CLIENT interface).
404 */
405 .max_interfaces = WLAN_MAX_INTERFACES,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800406 .n_limits = ARRAY_SIZE(wlan_hdd_iface_limit),
407 .beacon_int_infra_match = false,
408};
409#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800410
Jeff Johnson295189b2012-06-20 16:38:30 -0700411static struct cfg80211_ops wlan_hdd_cfg80211_ops;
412
413/* Data rate 100KBPS based on IE Index */
414struct index_data_rate_type
415{
416 v_U8_t beacon_rate_index;
417 v_U16_t supported_rate[4];
418};
419
420/* 11B, 11G Rate table include Basic rate and Extended rate
421 The IDX field is the rate index
422 The HI field is the rate when RSSI is strong or being ignored
423 (in this case we report actual rate)
424 The MID field is the rate when RSSI is moderate
425 (in this case we cap 11b rates at 5.5 and 11g rates at 24)
426 The LO field is the rate when RSSI is low
427 (in this case we don't report rates, actual current rate used)
428 */
429static const struct
430{
431 v_U8_t beacon_rate_index;
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700432 v_U16_t supported_rate[4];
Jeff Johnson295189b2012-06-20 16:38:30 -0700433} supported_data_rate[] =
434{
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700435/* IDX HI HM LM LO (RSSI-based index */
436 {2, { 10, 10, 10, 0}},
437 {4, { 20, 20, 10, 0}},
438 {11, { 55, 20, 10, 0}},
439 {12, { 60, 55, 20, 0}},
440 {18, { 90, 55, 20, 0}},
441 {22, {110, 55, 20, 0}},
442 {24, {120, 90, 60, 0}},
443 {36, {180, 120, 60, 0}},
444 {44, {220, 180, 60, 0}},
445 {48, {240, 180, 90, 0}},
446 {66, {330, 180, 90, 0}},
447 {72, {360, 240, 90, 0}},
448 {96, {480, 240, 120, 0}},
449 {108, {540, 240, 120, 0}}
Jeff Johnson295189b2012-06-20 16:38:30 -0700450};
451
452/* MCS Based rate table */
453static struct index_data_rate_type supported_mcs_rate[] =
454{
455/* MCS L20 L40 S20 S40 */
456 {0, {65, 135, 72, 150}},
457 {1, {130, 270, 144, 300}},
458 {2, {195, 405, 217, 450}},
459 {3, {260, 540, 289, 600}},
460 {4, {390, 810, 433, 900}},
461 {5, {520, 1080, 578, 1200}},
462 {6, {585, 1215, 650, 1350}},
463 {7, {650, 1350, 722, 1500}}
464};
465
466extern struct net_device_ops net_ops_struct;
467
468/*
469 * FUNCTION: wlan_hdd_cfg80211_init
470 * This function is called by hdd_wlan_startup()
471 * during initialization.
472 * This function is used to initialize and register wiphy structure.
473 */
474struct wiphy *wlan_hdd_cfg80211_init(int priv_size)
475{
476 struct wiphy *wiphy;
477 ENTER();
478
479 /*
480 * Create wiphy device
481 */
482 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
483
484 if (!wiphy)
485 {
486 /* Print error and jump into err label and free the memory */
487 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__);
488 return NULL;
489 }
490
491 return wiphy;
492}
493
494/*
495 * FUNCTION: wlan_hdd_cfg80211_update_band
496 * This function is called from the supplicant through a
497 * private ioctl to change the band value
498 */
499int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
500{
Jeff Johnsone7245742012-09-05 17:12:55 -0700501 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700502 switch(eBand)
503 {
504 case eCSR_BAND_24:
505 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
506 wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
507 break;
508 case eCSR_BAND_5G:
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700509 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700510 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
511 break;
512 case eCSR_BAND_ALL:
513 default:
514 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
515 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
516 }
517 return 0;
518}
519/*
520 * FUNCTION: wlan_hdd_cfg80211_init
521 * This function is called by hdd_wlan_startup()
522 * during initialization.
523 * This function is used to initialize and register wiphy structure.
524 */
525int wlan_hdd_cfg80211_register(struct device *dev,
526 struct wiphy *wiphy,
527 hdd_config_t *pCfg
528 )
529{
Jeff Johnsone7245742012-09-05 17:12:55 -0700530 ENTER();
531
Jeff Johnson295189b2012-06-20 16:38:30 -0700532 /* Now bind the underlying wlan device with wiphy */
533 set_wiphy_dev(wiphy, dev);
534
535 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
536
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700537 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700538
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700539#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700540 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
541 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
542 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
Jeff Johnsone7245742012-09-05 17:12:55 -0700543 | WIPHY_FLAG_OFFCHAN_TX;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700544#endif
James Zmuda77fb5ae2013-01-29 08:00:17 -0800545#ifdef FEATURE_WLAN_LFR
546 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
547#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800548#ifdef FEATURE_WLAN_TDLS
549 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
550 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
551#endif
552
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700553 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
554 driver can still register regulatory callback and
555 it will get CRDA setting in wiphy->band[], but
556 driver need to determine what to do with both
557 regulatory settings */
558 wiphy->reg_notifier = wlan_hdd_crda_reg_notifier;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700559
Jeff Johnson295189b2012-06-20 16:38:30 -0700560 wiphy->max_scan_ssids = MAX_SCAN_SSID;
561
562 wiphy->max_scan_ie_len = 200 ; //TODO: define a macro
563
564 /* Supports STATION & AD-HOC modes right now */
565 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
566 | BIT(NL80211_IFTYPE_ADHOC)
Jeff Johnson295189b2012-06-20 16:38:30 -0700567 | BIT(NL80211_IFTYPE_P2P_CLIENT)
568 | BIT(NL80211_IFTYPE_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -0700569 | BIT(NL80211_IFTYPE_AP);
570
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800571#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800572 if( pCfg->enableMCC )
573 {
574 /* Currently, supports up to two channels */
575 wlan_hdd_iface_combination.num_different_channels = 2;
576
577 if( !pCfg->allowMCCGODiffBI )
578 wlan_hdd_iface_combination.beacon_int_infra_match = true;
579
580 }
581 wiphy->iface_combinations = &wlan_hdd_iface_combination;
582 wiphy->n_iface_combinations = 1;
583#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800584
Jeff Johnson295189b2012-06-20 16:38:30 -0700585 /* Before registering we need to update the ht capabilitied based
586 * on ini values*/
587 if( !pCfg->ShortGI20MhzEnable )
588 {
589 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
590 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
591 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
592 }
593
594 if( !pCfg->ShortGI40MhzEnable )
595 {
596 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
597 }
598
599 if( !pCfg->nChannelBondingMode5GHz )
600 {
601 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
602 }
603
604 /*Initialize band capability*/
605 switch(pCfg->nBandCapability)
606 {
607 case eCSR_BAND_24:
608 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
609 break;
610 case eCSR_BAND_5G:
Jeff Johnson295189b2012-06-20 16:38:30 -0700611 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700612 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
613 break;
614 case eCSR_BAND_ALL:
615 default:
616 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
617 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
618 }
619 /*Initialise the supported cipher suite details*/
620 wiphy->cipher_suites = hdd_cipher_suites;
621 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
622
623 /*signal strength in mBm (100*dBm) */
624 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
625
626#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -0700627 wiphy->max_remain_on_channel_duration = 1000;
628#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700629
630 /* Register our wiphy dev with cfg80211 */
631 if (0 > wiphy_register(wiphy))
632 {
633 /* print eror */
634 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
635 return -EIO;
636 }
637
638 EXIT();
639 return 0;
640}
641
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700642/* In this function we will try to get default country code from crda.
643 If the gCrdaDefaultCountryCode is configured in ini file,
644 we will try to call user space crda to get the regulatory settings for
645 that country. We will timeout if we can't get it from crda.
646 It's called by hdd_wlan_startup() after wlan_hdd_cfg80211_register.
647*/
648int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg)
649{
650 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
651 if (memcmp(pCfg->crdaDefaultCountryCode,
652 CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) != 0)
653 {
654 init_completion(&pHddCtx->driver_crda_req);
655 regulatory_hint(wiphy, pCfg->crdaDefaultCountryCode);
656 wait_for_completion_interruptible_timeout(&pHddCtx->driver_crda_req,
657 CRDA_WAIT_TIME);
658 }
659 return 0;
660}
661
Jeff Johnson295189b2012-06-20 16:38:30 -0700662/* In this function we will do all post VOS start initialization.
663 In this function we will register for all frame in which supplicant
664 is interested.
665*/
666void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
667{
Jeff Johnson295189b2012-06-20 16:38:30 -0700668 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
669 /* Register for all P2P action, public action etc frames */
670 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
671
Jeff Johnsone7245742012-09-05 17:12:55 -0700672 ENTER();
673
Jeff Johnson295189b2012-06-20 16:38:30 -0700674 /* Right now we are registering these frame when driver is getting
675 initialized. Once we will move to 2.6.37 kernel, in which we have
676 frame register ops, we will move this code as a part of that */
677 /* GAS Initial Request */
678 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
679 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
680
681 /* GAS Initial Response */
682 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
683 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
684
685 /* GAS Comeback Request */
686 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
687 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
688
689 /* GAS Comeback Response */
690 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
691 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
692
693 /* P2P Public Action */
694 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
695 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
696 P2P_PUBLIC_ACTION_FRAME_SIZE );
697
698 /* P2P Action */
699 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
700 (v_U8_t*)P2P_ACTION_FRAME,
701 P2P_ACTION_FRAME_SIZE );
Jeff Johnson295189b2012-06-20 16:38:30 -0700702}
703
704void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
705{
Jeff Johnson295189b2012-06-20 16:38:30 -0700706 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
707 /* Register for all P2P action, public action etc frames */
708 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
709
Jeff Johnsone7245742012-09-05 17:12:55 -0700710 ENTER();
711
Jeff Johnson295189b2012-06-20 16:38:30 -0700712 /* Right now we are registering these frame when driver is getting
713 initialized. Once we will move to 2.6.37 kernel, in which we have
714 frame register ops, we will move this code as a part of that */
715 /* GAS Initial Request */
716
717 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
718 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
719
720 /* GAS Initial Response */
721 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
722 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
723
724 /* GAS Comeback Request */
725 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
726 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
727
728 /* GAS Comeback Response */
729 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
730 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
731
732 /* P2P Public Action */
733 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
734 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
735 P2P_PUBLIC_ACTION_FRAME_SIZE );
736
737 /* P2P Action */
738 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
739 (v_U8_t*)P2P_ACTION_FRAME,
740 P2P_ACTION_FRAME_SIZE );
Jeff Johnson295189b2012-06-20 16:38:30 -0700741}
742
743#ifdef FEATURE_WLAN_WAPI
744void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
745 const u8 *mac_addr, u8 *key , int key_Len)
746{
747 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
748 tCsrRoamSetKey setKey;
749 v_BOOL_t isConnected = TRUE;
750 int status = 0;
751 v_U32_t roamId= 0xFF;
752 tANI_U8 *pKeyPtr = NULL;
753 int n = 0;
754
755 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
756 __func__,pAdapter->device_mode);
757
Gopichand Nakkalae7480202013-02-11 15:24:22 +0530758 vos_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Jeff Johnson295189b2012-06-20 16:38:30 -0700759 setKey.keyId = key_index; // Store Key ID
760 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
761 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
762 setKey.paeRole = 0 ; // the PAE role
763 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
764 {
765 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
766 }
767 else
768 {
769 isConnected = hdd_connIsConnected(pHddStaCtx);
770 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
771 }
772 setKey.keyLength = key_Len;
773 pKeyPtr = setKey.Key;
774 memcpy( pKeyPtr, key, key_Len);
775
776 hddLog(VOS_TRACE_LEVEL_INFO,"\n%s: WAPI KEY LENGTH:0x%04x",
777 __func__, key_Len);
778 for (n = 0 ; n < key_Len; n++)
779 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
780 __func__,n,setKey.Key[n]);
781
782 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
783 if ( isConnected )
784 {
785 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
786 pAdapter->sessionId, &setKey, &roamId );
787 }
788 if ( status != 0 )
789 {
790 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
791 "[%4d] sme_RoamSetKey returned ERROR status= %d",
792 __LINE__, status );
793 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
794 }
795}
796#endif /* FEATURE_WLAN_WAPI*/
797
798#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
799int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
800 beacon_data_t **ppBeacon,
801 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700802#else
803int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
804 beacon_data_t **ppBeacon,
805 struct cfg80211_beacon_data *params,
806 int dtim_period)
807#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700808{
809 int size;
810 beacon_data_t *beacon = NULL;
811 beacon_data_t *old = NULL;
812 int head_len,tail_len;
813
Jeff Johnsone7245742012-09-05 17:12:55 -0700814 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700815 if (params->head && !params->head_len)
816 return -EINVAL;
817
818 old = pAdapter->sessionCtx.ap.beacon;
819
820 if (!params->head && !old)
821 return -EINVAL;
822
823 if (params->tail && !params->tail_len)
824 return -EINVAL;
825
826#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
827 /* Kernel 3.0 is not updating dtim_period for set beacon */
828 if (!params->dtim_period)
829 return -EINVAL;
830#endif
831
832 if(params->head)
833 head_len = params->head_len;
834 else
835 head_len = old->head_len;
836
837 if(params->tail || !old)
838 tail_len = params->tail_len;
839 else
840 tail_len = old->tail_len;
841
842 size = sizeof(beacon_data_t) + head_len + tail_len;
843
844 beacon = kzalloc(size, GFP_KERNEL);
845
846 if( beacon == NULL )
847 return -ENOMEM;
848
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700849#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700850 if(params->dtim_period || !old )
851 beacon->dtim_period = params->dtim_period;
852 else
853 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700854#else
855 if(dtim_period || !old )
856 beacon->dtim_period = dtim_period;
857 else
858 beacon->dtim_period = old->dtim_period;
859#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700860
861 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
862 beacon->tail = beacon->head + head_len;
863 beacon->head_len = head_len;
864 beacon->tail_len = tail_len;
865
866 if(params->head) {
867 memcpy (beacon->head,params->head,beacon->head_len);
868 }
869 else {
870 if(old)
871 memcpy (beacon->head,old->head,beacon->head_len);
872 }
873
874 if(params->tail) {
875 memcpy (beacon->tail,params->tail,beacon->tail_len);
876 }
877 else {
878 if(old)
879 memcpy (beacon->tail,old->tail,beacon->tail_len);
880 }
881
882 *ppBeacon = beacon;
883
884 kfree(old);
885
886 return 0;
887
888}
Jeff Johnson295189b2012-06-20 16:38:30 -0700889
890v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
891{
892 int left = length;
893 v_U8_t *ptr = pIes;
894 v_U8_t elem_id,elem_len;
895
896 while(left >= 2)
897 {
898 elem_id = ptr[0];
899 elem_len = ptr[1];
900 left -= 2;
901 if(elem_len > left)
902 {
903 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700904 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -0700905 eid,elem_len,left);
906 return NULL;
907 }
908 if (elem_id == eid)
909 {
910 return ptr;
911 }
912
913 left -= elem_len;
914 ptr += (elem_len + 2);
915 }
916 return NULL;
917}
918
Jeff Johnson295189b2012-06-20 16:38:30 -0700919/* Check if rate is 11g rate or not */
920static int wlan_hdd_rate_is_11g(u8 rate)
921{
922 u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 104}; /* actual rate * 2 */
923 u8 i;
924 for (i = 0; i < 8; i++)
925 {
926 if(rate == gRateArray[i])
927 return TRUE;
928 }
929 return FALSE;
930}
931
932/* Check for 11g rate and set proper 11g only mode */
933static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
934 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
935{
936 u8 i, num_rates = pIe[0];
937
938 pIe += 1;
939 for ( i = 0; i < num_rates; i++)
940 {
941 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
942 {
943 /* If rate set have 11g rate than change the mode to 11G */
944 *pSapHw_mode = eSAP_DOT11_MODE_11g;
945 if (pIe[i] & BASIC_RATE_MASK)
946 {
947 /* If we have 11g rate as basic rate, it means mode
948 is 11g only mode.
949 */
950 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
951 *pCheckRatesfor11g = FALSE;
952 }
953 }
954 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
955 {
956 *require_ht = TRUE;
957 }
958 }
959 return;
960}
961
962static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
963{
964 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
965 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
966 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
967 u8 checkRatesfor11g = TRUE;
968 u8 require_ht = FALSE;
969 u8 *pIe=NULL;
970
971 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
972
973 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
974 pBeacon->head_len, WLAN_EID_SUPP_RATES);
975 if (pIe != NULL)
976 {
977 pIe += 1;
978 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
979 &pConfig->SapHw_mode);
980 }
981
982 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
983 WLAN_EID_EXT_SUPP_RATES);
984 if (pIe != NULL)
985 {
986
987 pIe += 1;
988 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
989 &pConfig->SapHw_mode);
990 }
991
992 if( pConfig->channel > 14 )
993 {
994 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
995 }
996
997 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
998 WLAN_EID_HT_CAPABILITY);
999
1000 if(pIe)
1001 {
1002 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
1003 if(require_ht)
1004 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
1005 }
1006}
1007
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001008#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001009static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1010 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001011#else
1012static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1013 struct cfg80211_beacon_data *params)
1014#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001015{
1016 v_U8_t *genie;
1017 v_U8_t total_ielen = 0, ielen = 0;
1018 v_U8_t *pIe = NULL;
1019 v_U8_t addIE[1] = {0};
1020 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
Jeff Johnsone7245742012-09-05 17:12:55 -07001021 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001022
1023 genie = vos_mem_malloc(MAX_GENIE_LEN);
1024
1025 if(genie == NULL) {
1026
1027 return -ENOMEM;
1028 }
1029
1030 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1031
1032 if(pIe)
1033 {
1034 /*Copy the wps IE*/
1035 ielen = pIe[1] + 2;
1036 if( ielen <=MAX_GENIE_LEN)
1037 {
1038 vos_mem_copy(genie, pIe, ielen);
1039 }
1040 else
1041 {
1042 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001043 ret = -EINVAL;
1044 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001045 }
1046 total_ielen = ielen;
1047 }
1048
1049#ifdef WLAN_FEATURE_WFD
1050 pIe = wlan_hdd_get_wfd_ie_ptr(pBeacon->tail,pBeacon->tail_len);
1051
1052 if(pIe)
1053 {
1054 ielen = pIe[1] + 2;
1055 if(total_ielen + ielen <= MAX_GENIE_LEN) {
1056 vos_mem_copy(&genie[total_ielen],pIe,(pIe[1] + 2));
1057 }
1058 else {
1059 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie + P2p Ie + Wfd Ie Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001060 ret = -EINVAL;
1061 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001062 }
1063 total_ielen += ielen;
1064 }
1065#endif
1066
Jeff Johnson295189b2012-06-20 16:38:30 -07001067 pIe = wlan_hdd_get_p2p_ie_ptr(pBeacon->tail,pBeacon->tail_len);
1068
1069 if(pIe)
1070 {
1071 ielen = pIe[1] + 2;
1072 if(total_ielen + ielen <= MAX_GENIE_LEN)
1073 {
1074 vos_mem_copy(&genie[total_ielen], pIe, (pIe[1] + 2));
1075 }
1076 else
1077 {
1078 hddLog( VOS_TRACE_LEVEL_ERROR,
1079 "**Wps Ie+ P2pIE Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001080 ret = -EINVAL;
1081 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001082 }
1083 total_ielen += ielen;
1084 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001085
1086 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1087 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1088 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1089 {
1090 hddLog(LOGE,
1091 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001092 ret = -EINVAL;
1093 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001094 }
1095
1096 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1097 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1098 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1099 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1100 ==eHAL_STATUS_FAILURE)
1101 {
1102 hddLog(LOGE,
1103 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001104 ret = -EINVAL;
1105 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001106 }
1107
1108 // Added for ProResp IE
1109 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1110 {
1111 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1112 u8 probe_rsp_ie_len[3] = {0};
1113 u8 counter = 0;
1114 /* Check Probe Resp Length if it is greater then 255 then Store
1115 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1116 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1117 Store More then 255 bytes into One Variable.
1118 */
1119 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1120 {
1121 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1122 {
1123 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1124 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1125 }
1126 else
1127 {
1128 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1129 rem_probe_resp_ie_len = 0;
1130 }
1131 }
1132
1133 rem_probe_resp_ie_len = 0;
1134
1135 if (probe_rsp_ie_len[0] > 0)
1136 {
1137 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1138 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1139 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1140 probe_rsp_ie_len[0], NULL,
1141 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1142 {
1143 hddLog(LOGE,
1144 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001145 ret = -EINVAL;
1146 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001147 }
1148 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1149 }
1150
1151 if (probe_rsp_ie_len[1] > 0)
1152 {
1153 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1154 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1155 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1156 probe_rsp_ie_len[1], NULL,
1157 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1158 {
1159 hddLog(LOGE,
1160 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001161 ret = -EINVAL;
1162 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001163 }
1164 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1165 }
1166
1167 if (probe_rsp_ie_len[2] > 0)
1168 {
1169 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1170 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1171 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1172 probe_rsp_ie_len[2], NULL,
1173 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1174 {
1175 hddLog(LOGE,
1176 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001177 ret = -EINVAL;
1178 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001179 }
1180 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1181 }
1182
1183 if (probe_rsp_ie_len[1] == 0 )
1184 {
1185 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1186 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1187 eANI_BOOLEAN_FALSE) )
1188 {
1189 hddLog(LOGE,
1190 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1191 }
1192 }
1193
1194 if (probe_rsp_ie_len[2] == 0 )
1195 {
1196 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1197 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1198 eANI_BOOLEAN_FALSE) )
1199 {
1200 hddLog(LOGE,
1201 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1202 }
1203 }
1204
1205 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1206 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1207 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1208 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1209 == eHAL_STATUS_FAILURE)
1210 {
1211 hddLog(LOGE,
1212 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001213 ret = -EINVAL;
1214 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001215 }
1216 }
1217 else
1218 {
1219 // Reset WNI_CFG_PROBE_RSP Flags
1220 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1221
1222 hddLog(VOS_TRACE_LEVEL_INFO,
1223 "%s: No Probe Response IE received in set beacon",
1224 __func__);
1225 }
1226
1227 // Added for AssocResp IE
1228 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1229 {
1230 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1231 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1232 params->assocresp_ies_len, NULL,
1233 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1234 {
1235 hddLog(LOGE,
1236 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001237 ret = -EINVAL;
1238 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001239 }
1240
1241 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1242 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1243 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1244 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1245 == eHAL_STATUS_FAILURE)
1246 {
1247 hddLog(LOGE,
1248 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001249 ret = -EINVAL;
1250 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001251 }
1252 }
1253 else
1254 {
1255 hddLog(VOS_TRACE_LEVEL_INFO,
1256 "%s: No Assoc Response IE received in set beacon",
1257 __func__);
1258
1259 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1260 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1261 eANI_BOOLEAN_FALSE) )
1262 {
1263 hddLog(LOGE,
1264 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1265 }
1266 }
1267
Jeff Johnsone7245742012-09-05 17:12:55 -07001268done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001269 vos_mem_free(genie);
1270 return 0;
1271}
Jeff Johnson295189b2012-06-20 16:38:30 -07001272
1273/*
1274 * FUNCTION: wlan_hdd_validate_operation_channel
1275 * called by wlan_hdd_cfg80211_start_bss() and
1276 * wlan_hdd_cfg80211_set_channel()
1277 * This function validates whether given channel is part of valid
1278 * channel list.
1279 */
1280static VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
1281{
1282
1283 v_U32_t num_ch = 0;
1284 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1285 u32 indx = 0;
1286 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301287 v_U8_t fValidChannel = FALSE, count = 0;
1288 hdd_config_t *hdd_pConfig_ini= (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07001289
1290 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1291
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301292 if ( hdd_pConfig_ini->sapAllowAllChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001293 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301294 /* Validate the channel */
1295 for (count = RF_CHAN_1 ; count <= RF_CHAN_165 ; count++)
Jeff Johnson295189b2012-06-20 16:38:30 -07001296 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301297 if ( channel == rfChannels[count].channelNum )
1298 {
1299 fValidChannel = TRUE;
1300 break;
1301 }
1302 }
1303 if (fValidChannel != TRUE)
1304 {
1305 hddLog(VOS_TRACE_LEVEL_ERROR,
1306 "%s: Invalid Channel [%d]", __func__, channel);
1307 return VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001308 }
1309 }
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301310 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001311 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301312 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1313 valid_ch, &num_ch))
1314 {
1315 hddLog(VOS_TRACE_LEVEL_ERROR,
1316 "%s: failed to get valid channel list", __func__);
1317 return VOS_STATUS_E_FAILURE;
1318 }
1319 for (indx = 0; indx < num_ch; indx++)
1320 {
1321 if (channel == valid_ch[indx])
1322 {
1323 break;
1324 }
1325 }
1326
1327 if (indx >= num_ch)
1328 {
1329 hddLog(VOS_TRACE_LEVEL_ERROR,
1330 "%s: Invalid Channel [%d]", __func__, channel);
1331 return VOS_STATUS_E_FAILURE;
1332 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001333 }
1334 return VOS_STATUS_SUCCESS;
1335
1336}
1337
Viral Modi3a32cc52013-02-08 11:14:52 -08001338/**
1339 * FUNCTION: wlan_hdd_cfg80211_set_channel
1340 * This function is used to set the channel number
1341 */
1342static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
1343 struct ieee80211_channel *chan,
1344 enum nl80211_channel_type channel_type
1345 )
1346{
1347 v_U32_t num_ch = 0;
1348 u32 channel = 0;
1349 hdd_adapter_t *pAdapter = NULL;
1350 int freq = chan->center_freq; /* freq is in MHZ */
1351
1352 ENTER();
1353
1354 if( NULL == dev )
1355 {
1356 hddLog(VOS_TRACE_LEVEL_ERROR,
1357 "%s: Called with dev = NULL.\n", __func__);
1358 return -ENODEV;
1359 }
1360 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1361
1362 hddLog(VOS_TRACE_LEVEL_INFO,
1363 "%s: device_mode = %d freq = %d \n",__func__,
1364 pAdapter->device_mode, chan->center_freq);
1365 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1366 {
1367 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1368 return -EAGAIN;
1369 }
1370
1371 /*
1372 * Do freq to chan conversion
1373 * TODO: for 11a
1374 */
1375
1376 channel = ieee80211_frequency_to_channel(freq);
1377
1378 /* Check freq range */
1379 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
1380 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
1381 {
1382 hddLog(VOS_TRACE_LEVEL_ERROR,
1383 "%s: Channel [%d] is outside valid range from %d to %d\n",
1384 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
1385 WNI_CFG_CURRENT_CHANNEL_STAMAX);
1386 return -EINVAL;
1387 }
1388
1389 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1390
Gopichand Nakkala6ab19562013-03-07 13:59:42 +05301391 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode) &&
1392 (WLAN_HDD_P2P_GO != pAdapter->device_mode))
Viral Modi3a32cc52013-02-08 11:14:52 -08001393 {
1394 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
1395 {
1396 hddLog(VOS_TRACE_LEVEL_ERROR,
1397 "%s: Invalid Channel [%d] \n", __func__, channel);
1398 return -EINVAL;
1399 }
1400 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1401 "%s: set channel to [%d] for device mode =%d",
1402 __func__, channel,pAdapter->device_mode);
1403 }
1404 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Viral Modi3a32cc52013-02-08 11:14:52 -08001405 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Viral Modi3a32cc52013-02-08 11:14:52 -08001406 )
1407 {
1408 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
1409 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
1410 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1411
1412 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
1413 {
1414 /* Link is up then return cant set channel*/
1415 hddLog( VOS_TRACE_LEVEL_ERROR,
1416 "%s: IBSS Associated, can't set the channel\n", __func__);
1417 return -EINVAL;
1418 }
1419
1420 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
1421 pHddStaCtx->conn_info.operationChannel = channel;
1422 pRoamProfile->ChannelInfo.ChannelList =
1423 &pHddStaCtx->conn_info.operationChannel;
1424 }
1425 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Viral Modi3a32cc52013-02-08 11:14:52 -08001426 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Viral Modi3a32cc52013-02-08 11:14:52 -08001427 )
1428 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301429 if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
1430 {
1431 if(VOS_STATUS_SUCCESS !=
1432 wlan_hdd_validate_operation_channel(pAdapter,channel))
1433 {
1434 hddLog(VOS_TRACE_LEVEL_ERROR,
1435 "%s: Invalid Channel [%d] \n", __func__, channel);
1436 return -EINVAL;
1437 }
1438 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1439 }
1440 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
Viral Modi3a32cc52013-02-08 11:14:52 -08001441 {
1442 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
1443
1444 /* If auto channel selection is configured as enable/ 1 then ignore
1445 channel set by supplicant
1446 */
1447 if ( cfg_param->apAutoChannelSelection )
1448 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301449 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel =
1450 AUTO_CHANNEL_SELECT;
Viral Modi3a32cc52013-02-08 11:14:52 -08001451 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1452 "%s: set channel to auto channel (0) for device mode =%d",
1453 __func__, pAdapter->device_mode);
1454 }
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301455 else
1456 {
1457 if(VOS_STATUS_SUCCESS !=
1458 wlan_hdd_validate_operation_channel(pAdapter,channel))
1459 {
1460 hddLog(VOS_TRACE_LEVEL_ERROR,
1461 "%s: Invalid Channel [%d] \n", __func__, channel);
1462 return -EINVAL;
1463 }
1464 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1465 }
Viral Modi3a32cc52013-02-08 11:14:52 -08001466 }
1467 }
1468 else
1469 {
1470 hddLog(VOS_TRACE_LEVEL_FATAL,
1471 "%s: Invalid device mode failed to set valid channel", __func__);
1472 return -EINVAL;
1473 }
1474 EXIT();
1475 return 0;
1476}
1477
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301478/*
1479 * FUNCTION: wlan_hdd_select_cbmode
1480 * called by wlan_hdd_cfg80211_start_bss() and
1481 * This function selects the cbmode based on primary channel
1482 */
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001483VOS_STATUS wlan_sap_select_cbmode(void *pAdapter,eSapPhyMode SapHw_mode, v_U8_t channel)
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301484{
1485 tSmeConfigParams smeConfig;
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001486 hdd_context_t *pHddCtx = ( hdd_context_t *) pAdapter;
1487 hdd_config_t *pConfigIni = ((hdd_context_t *)(pAdapter))->cfg_ini;
1488
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301489 if(
1490#ifdef WLAN_FEATURE_11AC
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001491 SapHw_mode != eSAP_DOT11_MODE_11ac &&
1492 SapHw_mode != eSAP_DOT11_MODE_11ac_ONLY &&
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301493#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001494 SapHw_mode != eSAP_DOT11_MODE_11n &&
1495 SapHw_mode != eSAP_DOT11_MODE_11n_ONLY
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301496 )
1497 {
1498 return VOS_STATUS_SUCCESS;
1499 }
1500
1501 if (!pConfigIni->nChannelBondingMode5GHz) {
1502 return VOS_STATUS_SUCCESS;
1503 }
1504
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001505 //channel = pSapConfig->channel;
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301506 vos_mem_zero(&smeConfig, sizeof (tSmeConfigParams));
1507
1508 sme_GetConfigParam(pHddCtx->hHal, &smeConfig);
1509
1510#ifdef WLAN_FEATURE_11AC
1511
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001512 if ( SapHw_mode == eSAP_DOT11_MODE_11ac ||
1513 SapHw_mode == eSAP_DOT11_MODE_11ac_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301514 {
1515 if ( channel== 36 || channel == 52 || channel == 100 ||
1516 channel == 116 || channel == 149 )
1517 {
1518 smeConfig.csrConfig.channelBondingMode5GHz =
1519 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW - 1;
1520 }
1521 else if ( channel == 40 || channel == 56 || channel == 104 ||
1522 channel == 120 || channel == 153 )
1523 {
1524 smeConfig.csrConfig.channelBondingMode5GHz =
1525 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW - 1;
1526 }
1527 else if ( channel == 44 || channel == 60 || channel == 108 ||
1528 channel == 124 || channel == 157 )
1529 {
1530 smeConfig.csrConfig.channelBondingMode5GHz =
1531 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH -1;
1532 }
1533 else if ( channel == 48 || channel == 64 || channel == 112 ||
1534 channel == 128 || channel == 161 )
1535 {
1536 smeConfig.csrConfig.channelBondingMode5GHz =
1537 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH - 1;
1538 }
Shailender Karmuchi84f11f02013-02-12 17:11:45 -08001539 else if ( channel == 165 )
1540 {
1541 smeConfig.csrConfig.channelBondingMode5GHz = 0;
1542 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301543 }
1544#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001545 if ( SapHw_mode == eSAP_DOT11_MODE_11n ||
1546 SapHw_mode == eSAP_DOT11_MODE_11n_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301547 {
1548 if ( channel== 40 || channel == 48 || channel == 56 ||
1549 channel == 64 || channel == 104 || channel == 112 ||
1550 channel == 120 || channel == 128 || channel == 136 ||
1551 channel == 144 || channel == 153 || channel == 161 )
1552 {
1553 smeConfig.csrConfig.channelBondingMode5GHz = 1;
1554 }
1555 else if ( channel== 36 || channel == 44 || channel == 52 ||
1556 channel == 60 || channel == 100 || channel == 108 ||
1557 channel == 116 || channel == 124 || channel == 132 ||
1558 channel == 140 || channel == 149 || channel == 157 )
1559 {
1560 smeConfig.csrConfig.channelBondingMode5GHz = 2;
1561 }
Shailender Karmuchi84f11f02013-02-12 17:11:45 -08001562 else if ( channel == 165 )
1563 {
1564 smeConfig.csrConfig.channelBondingMode5GHz = 0;
1565 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301566 }
1567 pr_info ("cbmode selected=%ld\n",smeConfig.csrConfig.channelBondingMode5GHz);
1568
1569 sme_UpdateConfig (pHddCtx->hHal,&smeConfig);
1570 return VOS_STATUS_SUCCESS;
1571}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001572
Jeff Johnson295189b2012-06-20 16:38:30 -07001573#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1574static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1575 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001576#else
1577static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1578 struct cfg80211_beacon_data *params,
1579 const u8 *ssid, size_t ssid_len,
1580 enum nl80211_hidden_ssid hidden_ssid)
1581#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001582{
1583 tsap_Config_t *pConfig;
1584 beacon_data_t *pBeacon = NULL;
1585 struct ieee80211_mgmt *pMgmt_frame;
1586 v_U8_t *pIe=NULL;
1587 v_U16_t capab_info;
1588 eCsrAuthType RSNAuthType;
1589 eCsrEncryptionType RSNEncryptType;
1590 eCsrEncryptionType mcRSNEncryptType;
1591 int status = VOS_STATUS_SUCCESS;
1592 tpWLAN_SAPEventCB pSapEventCallback;
1593 hdd_hostapd_state_t *pHostapdState;
1594 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1595 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301596 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001597 struct qc_mac_acl_entry *acl_entry = NULL;
1598 v_SINT_t i;
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001599 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001600
1601 ENTER();
1602
1603 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1604
1605 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1606
1607 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1608
1609 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1610
1611 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1612
1613 //channel is already set in the set_channel Call back
1614 //pConfig->channel = pCommitConfig->channel;
1615
1616 /*Protection parameter to enable or disable*/
1617 pConfig->protEnabled =
1618 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1619
1620 pConfig->dtim_period = pBeacon->dtim_period;
1621
1622 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1623 pConfig->dtim_period);
1624
1625
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001626 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001627 {
1628 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001629 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001630 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001631 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001632 tANI_BOOLEAN restartNeeded;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001633 pConfig->ieee80211d = 1;
1634 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1635 sme_setRegInfo(hHal, pConfig->countryCode);
1636 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
Jeff Johnson295189b2012-06-20 16:38:30 -07001637 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001638 else
1639 {
1640 pConfig->ieee80211d = 0;
1641 }
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301642 /*
1643 * If auto channel is configured i.e. channel is 0,
1644 * so skip channel validation.
1645 */
1646 if( AUTO_CHANNEL_SELECT != pConfig->channel )
1647 {
1648 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1649 {
1650 hddLog(VOS_TRACE_LEVEL_ERROR,
1651 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1652 return -EINVAL;
1653 }
1654 }
1655 else
1656 {
1657 if(1 != pHddCtx->is_dynamic_channel_range_set)
1658 {
1659 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
1660 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
1661 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
1662 }
1663 pHddCtx->is_dynamic_channel_range_set = 0;
1664 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001665 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001666 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001667 {
1668 pConfig->ieee80211d = 0;
1669 }
1670 pConfig->authType = eSAP_AUTO_SWITCH;
1671
1672 capab_info = pMgmt_frame->u.beacon.capab_info;
1673
1674 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
1675 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1676
1677 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1678
1679 /*Set wps station to configured*/
1680 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1681
1682 if(pIe)
1683 {
1684 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1685 {
1686 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1687 return -EINVAL;
1688 }
1689 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1690 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001691 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001692 /* Check 15 bit of WPS IE as it contain information for wps state
1693 * WPS state
1694 */
1695 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1696 {
1697 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1698 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1699 {
1700 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1701 }
1702 }
1703 }
1704 else
1705 {
1706 pConfig->wps_state = SAP_WPS_DISABLED;
1707 }
1708 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
1709
1710 pConfig->RSNWPAReqIELength = 0;
1711 pConfig->pRSNWPAReqIE = NULL;
1712 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1713 WLAN_EID_RSN);
1714 if(pIe && pIe[1])
1715 {
1716 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1717 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1718 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1719 /* The actual processing may eventually be more extensive than
1720 * this. Right now, just consume any PMKIDs that are sent in
1721 * by the app.
1722 * */
1723 status = hdd_softap_unpackIE(
1724 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1725 &RSNEncryptType,
1726 &mcRSNEncryptType,
1727 &RSNAuthType,
1728 pConfig->pRSNWPAReqIE[1]+2,
1729 pConfig->pRSNWPAReqIE );
1730
1731 if( VOS_STATUS_SUCCESS == status )
1732 {
1733 /* Now copy over all the security attributes you have
1734 * parsed out
1735 * */
1736 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1737 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1738 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1739 = RSNEncryptType;
1740 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1741 "EncryptionType = %d mcEncryptionType = %d\n"),
1742 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1743 }
1744 }
1745
1746 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1747 pBeacon->tail, pBeacon->tail_len);
1748
1749 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1750 {
1751 if (pConfig->pRSNWPAReqIE)
1752 {
1753 /*Mixed mode WPA/WPA2*/
1754 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1755 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1756 }
1757 else
1758 {
1759 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1760 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1761 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1762 status = hdd_softap_unpackIE(
1763 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1764 &RSNEncryptType,
1765 &mcRSNEncryptType,
1766 &RSNAuthType,
1767 pConfig->pRSNWPAReqIE[1]+2,
1768 pConfig->pRSNWPAReqIE );
1769
1770 if( VOS_STATUS_SUCCESS == status )
1771 {
1772 /* Now copy over all the security attributes you have
1773 * parsed out
1774 * */
1775 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1776 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1777 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1778 = RSNEncryptType;
1779 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1780 "EncryptionType = %d mcEncryptionType = %d\n"),
1781 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1782 }
1783 }
1784 }
1785
1786 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1787
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001788#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001789 if (params->ssid != NULL)
1790 {
1791 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1792 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1793 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1794 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1795 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001796#else
1797 if (ssid != NULL)
1798 {
1799 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1800 pConfig->SSIDinfo.ssid.length = ssid_len;
1801 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1802 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1803 }
1804#endif
1805
Jeff Johnson295189b2012-06-20 16:38:30 -07001806 vos_mem_copy(pConfig->self_macaddr.bytes,
1807 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1808
1809 /* default value */
1810 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1811 pConfig->num_accept_mac = 0;
1812 pConfig->num_deny_mac = 0;
1813
1814 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1815 pBeacon->tail, pBeacon->tail_len);
1816
1817 /* pIe for black list is following form:
1818 type : 1 byte
1819 length : 1 byte
1820 OUI : 4 bytes
1821 acl type : 1 byte
1822 no of mac addr in black list: 1 byte
1823 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1824 */
1825 if ((pIe != NULL) && (pIe[1] != 0))
1826 {
1827 pConfig->SapMacaddr_acl = pIe[6];
1828 pConfig->num_deny_mac = pIe[7];
1829 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1830 pIe[6], pIe[7]);
1831 if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
1832 pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
1833 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1834 for (i = 0; i < pConfig->num_deny_mac; i++)
1835 {
1836 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1837 acl_entry++;
1838 }
1839 }
1840 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1841 pBeacon->tail, pBeacon->tail_len);
1842
1843 /* pIe for white list is following form:
1844 type : 1 byte
1845 length : 1 byte
1846 OUI : 4 bytes
1847 acl type : 1 byte
1848 no of mac addr in white list: 1 byte
1849 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1850 */
1851 if ((pIe != NULL) && (pIe[1] != 0))
1852 {
1853 pConfig->SapMacaddr_acl = pIe[6];
1854 pConfig->num_accept_mac = pIe[7];
1855 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
1856 pIe[6], pIe[7]);
1857 if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
1858 pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
1859 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1860 for (i = 0; i < pConfig->num_accept_mac; i++)
1861 {
1862 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1863 acl_entry++;
1864 }
1865 }
1866 wlan_hdd_set_sapHwmode(pHostapdAdapter);
1867
Jeff Johnsone7245742012-09-05 17:12:55 -07001868#ifdef WLAN_FEATURE_11AC
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08001869 /* Overwrite the hostapd setting for HW mode only for 11ac.
1870 * This is valid only if mode is set to 11n in hostapd and either AUTO or 11ac in .ini .
1871 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode) */
1872 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
1873 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
1874 (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
1875 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1876 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07001877 {
1878 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
1879 }
1880#endif
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301881
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001882 if( AUTO_CHANNEL_SELECT != pConfig->channel)
1883 wlan_sap_select_cbmode((WLAN_HDD_GET_CTX(pHostapdAdapter)),pConfig->SapHw_mode,pConfig->channel);
Jeff Johnson295189b2012-06-20 16:38:30 -07001884 // ht_capab is not what the name conveys,this is used for protection bitmap
1885 pConfig->ht_capab =
1886 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
1887
1888 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
1889 {
1890 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
1891 return -EINVAL;
1892 }
1893
1894 //Uapsd Enabled Bit
1895 pConfig->UapsdEnable =
1896 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
1897 //Enable OBSS protection
1898 pConfig->obssProtEnabled =
1899 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
1900
1901 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
1902 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
1903 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
1904 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
1905 (int)pConfig->channel);
1906 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
1907 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
1908 pConfig->authType);
1909 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
1910 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
1911 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
1912 pConfig->protEnabled, pConfig->obssProtEnabled);
1913
1914 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
1915 {
1916 //Bss already started. just return.
1917 //TODO Probably it should update some beacon params.
1918 hddLog( LOGE, "Bss Already started...Ignore the request");
1919 EXIT();
1920 return 0;
1921 }
1922
1923 pConfig->persona = pHostapdAdapter->device_mode;
1924
1925 pSapEventCallback = hdd_hostapd_SAPEventCB;
1926 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
1927 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
1928 {
1929 hddLog(LOGE,FL("SAP Start Bss fail\n"));
1930 return -EINVAL;
1931 }
1932
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001933 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07001934 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
1935
1936 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1937
1938 if (!VOS_IS_STATUS_SUCCESS(status))
1939 {
1940 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1941 ("ERROR: HDD vos wait for single_event failed!!\n"));
1942 VOS_ASSERT(0);
1943 }
1944
1945 //Succesfully started Bss update the state bit.
1946 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
1947
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001948#ifdef WLAN_FEATURE_P2P_DEBUG
1949 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
1950 {
1951 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
1952 {
1953 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1954 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001955 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001956 }
1957 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
1958 {
1959 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1960 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001961 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001962 }
1963 }
1964#endif
1965
Jeff Johnson295189b2012-06-20 16:38:30 -07001966 pHostapdState->bCommit = TRUE;
1967 EXIT();
1968
1969 return 0;
1970}
1971
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001972#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001973static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
1974 struct net_device *dev,
1975 struct beacon_parameters *params)
1976{
1977 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1978 int status=VOS_STATUS_SUCCESS;
1979
1980 ENTER();
1981
1982 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
1983
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001984 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1985 {
1986 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1987 "%s:LOGP in Progress. Ignore!!!", __func__);
1988 return -EAGAIN;
1989 }
1990
Jeff Johnson295189b2012-06-20 16:38:30 -07001991 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07001992 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07001993 )
1994 {
1995 beacon_data_t *old,*new;
1996
1997 old = pAdapter->sessionCtx.ap.beacon;
1998
1999 if (old)
2000 return -EALREADY;
2001
2002 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2003
2004 if(status != VOS_STATUS_SUCCESS)
2005 {
2006 hddLog(VOS_TRACE_LEVEL_FATAL,
2007 "%s:Error!!! Allocating the new beacon\n",__func__);
2008 return -EINVAL;
2009 }
2010
2011 pAdapter->sessionCtx.ap.beacon = new;
2012
2013 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2014 }
2015
2016 EXIT();
2017 return status;
2018}
2019
2020static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
2021 struct net_device *dev,
2022 struct beacon_parameters *params)
2023{
2024 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2025 int status=VOS_STATUS_SUCCESS;
2026
2027 ENTER();
2028
2029 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2030 __func__,pAdapter->device_mode);
2031
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002032 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2033 {
2034 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2035 "%s:LOGP in Progress. Ignore!!!", __func__);
2036 return -EAGAIN;
2037 }
2038
Jeff Johnson295189b2012-06-20 16:38:30 -07002039 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002040 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002041 )
2042 {
2043 beacon_data_t *old,*new;
2044
2045 old = pAdapter->sessionCtx.ap.beacon;
2046
2047 if (!old)
2048 return -ENOENT;
2049
2050 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2051
2052 if(status != VOS_STATUS_SUCCESS) {
2053 hddLog(VOS_TRACE_LEVEL_FATAL,
2054 "%s: Error!!! Allocating the new beacon\n",__func__);
2055 return -EINVAL;
2056 }
2057
2058 pAdapter->sessionCtx.ap.beacon = new;
2059
2060 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2061 }
2062
2063 EXIT();
2064 return status;
2065}
2066
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002067#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
2068
2069#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002070static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
2071 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002072#else
2073static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
2074 struct net_device *dev)
2075#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002076{
2077 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07002078 hdd_context_t *pHddCtx = NULL;
2079 hdd_scaninfo_t *pScanInfo = NULL;
2080 hdd_adapter_t *staAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002081 VOS_STATUS status = 0;
2082
2083 ENTER();
2084
2085 if (NULL == pAdapter)
2086 {
2087 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002088 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002089 return -ENODEV;
2090 }
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002091 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2092 {
2093 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2094 "%s:LOGP in Progress. Ignore!!!", __func__);
2095 return -EAGAIN;
2096 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002097
2098 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2099 if (NULL == pHddCtx)
2100 {
2101 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002102 "%s: HDD context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002103 return -ENODEV;
2104 }
2105
2106 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
2107 if (NULL == staAdapter)
2108 {
2109 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
2110 if (NULL == staAdapter)
2111 {
2112 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002113 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002114 return -ENODEV;
2115 }
2116 }
2117
2118 pScanInfo = &pHddCtx->scan_info;
2119
Jeff Johnson295189b2012-06-20 16:38:30 -07002120 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2121 {
2122 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2123 return -EAGAIN;
2124 }
2125
2126 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2127
2128 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2129 __func__,pAdapter->device_mode);
2130
Jeff Johnsone7245742012-09-05 17:12:55 -07002131 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
2132 {
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002133 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Jeff Johnsone7245742012-09-05 17:12:55 -07002134 hdd_abort_mac_scan(staAdapter->pHddCtx);
2135 status = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002136 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07002137 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
2138 if (!status)
2139 {
2140 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson902c9832012-12-10 14:28:09 -08002141 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002142 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07002143 VOS_ASSERT(pScanInfo->mScanPending);
2144 return 0;
2145 }
2146 }
2147
Jeff Johnson295189b2012-06-20 16:38:30 -07002148 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002149 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002150 )
2151 {
2152 beacon_data_t *old;
2153
2154 old = pAdapter->sessionCtx.ap.beacon;
2155
2156 if (!old)
2157 return -ENOENT;
2158
Jeff Johnson295189b2012-06-20 16:38:30 -07002159 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002160
2161 mutex_lock(&pHddCtx->sap_lock);
2162 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2163 {
2164 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss((WLAN_HDD_GET_CTX(pAdapter))->pvosContext) ) )
2165 {
2166 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2167
2168 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2169
2170 if (!VOS_IS_STATUS_SUCCESS(status))
2171 {
2172 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2173 ("ERROR: HDD vos wait for single_event failed!!\n"));
2174 VOS_ASSERT(0);
2175 }
2176 }
2177 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2178 }
2179 mutex_unlock(&pHddCtx->sap_lock);
2180
2181 if(status != VOS_STATUS_SUCCESS)
2182 {
2183 hddLog(VOS_TRACE_LEVEL_FATAL,
2184 "%s:Error!!! Stopping the BSS\n",__func__);
2185 return -EINVAL;
2186 }
2187
2188 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2189 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
2190 ==eHAL_STATUS_FAILURE)
2191 {
2192 hddLog(LOGE,
2193 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
2194 }
2195
2196 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2197 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2198 eANI_BOOLEAN_FALSE) )
2199 {
2200 hddLog(LOGE,
2201 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
2202 }
2203
2204 // Reset WNI_CFG_PROBE_RSP Flags
2205 wlan_hdd_reset_prob_rspies(pAdapter);
2206
2207 pAdapter->sessionCtx.ap.beacon = NULL;
2208 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002209#ifdef WLAN_FEATURE_P2P_DEBUG
2210 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
2211 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
2212 {
2213 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
2214 "GO got removed");
2215 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
2216 }
2217#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002218 }
2219 EXIT();
2220 return status;
2221}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002222
2223#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2224
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302225static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2226 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002227 struct cfg80211_ap_settings *params)
2228{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302229 hdd_adapter_t *pAdapter;
2230 hdd_context_t *pHddCtx;
2231 int status = 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002232
2233 ENTER();
2234
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302235 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002236 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302237 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2238 "%s: Device is Null", __func__);
2239 return -ENODEV;
2240 }
2241
2242 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2243 if (NULL == pAdapter)
2244 {
2245 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2246 "%s: HDD adapter is Null", __func__);
2247 return -ENODEV;
2248 }
2249
2250 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2251 {
2252 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2253 "%s: HDD adapter magic is invalid", __func__);
2254 return -ENODEV;
2255 }
2256
2257 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2258 if (NULL == pHddCtx)
2259 {
2260 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2261 "%s: HDD context is Null", __func__);
2262 return -ENODEV;
2263 }
2264
2265 if (pHddCtx->isLogpInProgress)
2266 {
2267 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2268 "%s: LOGP in Progress. Ignore!!!", __func__);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002269 return -EAGAIN;
2270 }
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302271
2272 if (pHddCtx->isLoadUnloadInProgress)
2273 {
2274 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2275 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
2276 return -EAGAIN;
2277 }
2278
2279 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2280 __func__, pAdapter->device_mode);
2281
2282 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002283 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002284 )
2285 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302286 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002287
2288 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302289
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002290 if (old)
2291 return -EALREADY;
2292
2293 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2294
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302295 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002296 {
2297 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302298 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002299 return -EINVAL;
2300 }
2301 pAdapter->sessionCtx.ap.beacon = new;
Viral Modi3a32cc52013-02-08 11:14:52 -08002302#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2303 wlan_hdd_cfg80211_set_channel(wiphy, dev, params->channel, params->channel_type);
2304#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002305 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2306 params->ssid_len, params->hidden_ssid);
2307 }
2308
2309 EXIT();
2310 return status;
2311}
2312
2313
2314static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
2315 struct net_device *dev,
2316 struct cfg80211_beacon_data *params)
2317{
2318 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2319 int status=VOS_STATUS_SUCCESS;
2320
2321 ENTER();
2322
2323 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2324 __func__, pAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002325 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2326 {
2327 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2328 return -EAGAIN;
2329 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002330
2331 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002332 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002333 )
2334 {
2335 beacon_data_t *old,*new;
2336
2337 old = pAdapter->sessionCtx.ap.beacon;
2338
2339 if (!old)
2340 return -ENOENT;
2341
2342 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2343
2344 if(status != VOS_STATUS_SUCCESS) {
2345 hddLog(VOS_TRACE_LEVEL_FATAL,
2346 "%s: Error!!! Allocating the new beacon\n",__func__);
2347 return -EINVAL;
2348 }
2349
2350 pAdapter->sessionCtx.ap.beacon = new;
2351
2352 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2353 }
2354
2355 EXIT();
2356 return status;
2357}
2358
2359#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2360
Jeff Johnson295189b2012-06-20 16:38:30 -07002361
2362static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2363 struct net_device *dev,
2364 struct bss_parameters *params)
2365{
2366 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2367
2368 ENTER();
2369
2370 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2371 __func__,pAdapter->device_mode);
2372
2373 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002374 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002375 )
2376 {
2377 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2378 * want to update this parameter */
2379 if (-1 != params->ap_isolate)
2380 {
2381 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
2382 }
2383 }
2384
2385 EXIT();
2386 return 0;
2387}
2388
2389/*
2390 * FUNCTION: wlan_hdd_cfg80211_change_iface
2391 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2392 */
2393int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2394 struct net_device *ndev,
2395 enum nl80211_iftype type,
2396 u32 *flags,
2397 struct vif_params *params
2398 )
2399{
2400 struct wireless_dev *wdev;
2401 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2402 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002403 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002404 tCsrRoamProfile *pRoamProfile = NULL;
2405 eCsrRoamBssType LastBSSType;
2406 hdd_config_t *pConfig = pHddCtx->cfg_ini;
2407 eMib_dot11DesiredBssType connectedBssType;
2408 VOS_STATUS status;
2409
2410 ENTER();
2411
2412 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2413 {
2414 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2415 return -EAGAIN;
2416 }
2417
2418 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2419 __func__, pAdapter->device_mode);
2420
2421 wdev = ndev->ieee80211_ptr;
2422
2423#ifdef WLAN_BTAMP_FEATURE
2424 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2425 (NL80211_IFTYPE_ADHOC == type)||
2426 (NL80211_IFTYPE_AP == type)||
2427 (NL80211_IFTYPE_P2P_GO == type))
2428 {
2429 pHddCtx->isAmpAllowed = VOS_FALSE;
2430 // stop AMP traffic
2431 status = WLANBAP_StopAmp();
2432 if(VOS_STATUS_SUCCESS != status )
2433 {
2434 pHddCtx->isAmpAllowed = VOS_TRUE;
2435 hddLog(VOS_TRACE_LEVEL_FATAL,
2436 "%s: Failed to stop AMP", __func__);
2437 return -EINVAL;
2438 }
2439 }
2440#endif //WLAN_BTAMP_FEATURE
2441 /* Reset the current device mode bit mask*/
2442 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2443
2444 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07002445 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002446 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002447 )
2448 {
2449 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2450 pRoamProfile = &pWextState->roamProfile;
2451 LastBSSType = pRoamProfile->BSSType;
2452
2453 switch (type)
2454 {
2455 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002456 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002457 hddLog(VOS_TRACE_LEVEL_INFO,
2458 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2459 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002460#ifdef WLAN_FEATURE_11AC
2461 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2462 {
2463 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2464 }
2465#endif
2466 pRoamProfile->phyMode =
2467 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002468 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002469 //Check for sub-string p2p to confirm its a p2p interface
2470 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002471 {
2472 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2473 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2474 }
2475 else
2476 {
2477 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002478 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002479 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002480 break;
2481 case NL80211_IFTYPE_ADHOC:
2482 hddLog(VOS_TRACE_LEVEL_INFO,
2483 "%s: setting interface Type to ADHOC", __func__);
2484 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2485 pRoamProfile->phyMode =
2486 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
2487 wdev->iftype = type;
2488 break;
2489
2490 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002491 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002492 {
2493 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2494 "%s: setting interface Type to %s", __func__,
2495 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2496
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002497 //Cancel any remain on channel for GO mode
2498 if (NL80211_IFTYPE_P2P_GO == type)
2499 {
2500 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2501 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002502 if (NL80211_IFTYPE_AP == type)
2503 {
2504 /* As Loading WLAN Driver one interface being created for p2p device
2505 * address. This will take one HW STA and the max number of clients
2506 * that can connect to softAP will be reduced by one. so while changing
2507 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2508 * interface as it is not required in SoftAP mode.
2509 */
2510
2511 // Get P2P Adapter
2512 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2513
2514 if (pP2pAdapter)
2515 {
2516 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2517 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2518 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2519 }
2520 }
2521
Jeff Johnson295189b2012-06-20 16:38:30 -07002522 //De-init the adapter.
2523 hdd_stop_adapter( pHddCtx, pAdapter );
2524 hdd_deinit_adapter( pHddCtx, pAdapter );
2525 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
Jeff Johnson295189b2012-06-20 16:38:30 -07002526 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2527 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002528
2529 //Disable BMPS and IMPS if enabled
2530 //before starting Go
2531 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2532 {
2533 if(VOS_STATUS_E_FAILURE ==
2534 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2535 {
2536 //Fail to Exit BMPS
2537 VOS_ASSERT(0);
2538 }
2539 }
2540
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002541 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2542 (pConfig->apRandomBssidEnabled))
2543 {
2544 /* To meet Android requirements create a randomized
2545 MAC address of the form 02:1A:11:Fx:xx:xx */
2546 get_random_bytes(&ndev->dev_addr[3], 3);
2547 ndev->dev_addr[0] = 0x02;
2548 ndev->dev_addr[1] = 0x1A;
2549 ndev->dev_addr[2] = 0x11;
2550 ndev->dev_addr[3] |= 0xF0;
2551 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2552 VOS_MAC_ADDR_SIZE);
2553 pr_info("wlan: Generated HotSpot BSSID "
2554 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2555 ndev->dev_addr[0],
2556 ndev->dev_addr[1],
2557 ndev->dev_addr[2],
2558 ndev->dev_addr[3],
2559 ndev->dev_addr[4],
2560 ndev->dev_addr[5]);
2561 }
2562
Jeff Johnson295189b2012-06-20 16:38:30 -07002563 hdd_set_ap_ops( pAdapter->dev );
2564
2565 status = hdd_init_ap_mode(pAdapter);
2566 if(status != VOS_STATUS_SUCCESS)
2567 {
2568 hddLog(VOS_TRACE_LEVEL_FATAL,
2569 "%s: Error initializing the ap mode", __func__);
2570 return -EINVAL;
2571 }
2572 hdd_set_conparam(1);
2573
Jeff Johnson295189b2012-06-20 16:38:30 -07002574 /*interface type changed update in wiphy structure*/
2575 if(wdev)
2576 {
2577 wdev->iftype = type;
2578 pHddCtx->change_iface = type;
2579 }
2580 else
2581 {
2582 hddLog(VOS_TRACE_LEVEL_ERROR,
2583 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2584 return -EINVAL;
2585 }
2586 goto done;
2587 }
2588
2589 default:
2590 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2591 __func__);
2592 return -EOPNOTSUPP;
2593 }
2594 }
2595 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002596 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002597 )
2598 {
2599 switch(type)
2600 {
2601 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002602 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002603 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002604 hdd_stop_adapter( pHddCtx, pAdapter );
2605 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002606 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002607 //Check for sub-string p2p to confirm its a p2p interface
2608 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002609 {
2610 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2611 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2612 }
2613 else
2614 {
2615 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002616 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002617 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002618 hdd_set_conparam(0);
2619 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002620 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2621 hdd_set_station_ops( pAdapter->dev );
2622 status = hdd_init_station_mode( pAdapter );
2623 if( VOS_STATUS_SUCCESS != status )
2624 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002625 /* In case of JB, for P2P-GO, only change interface will be called,
2626 * This is the right place to enable back bmps_imps()
2627 */
2628 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002629 goto done;
2630 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002631 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002632 wdev->iftype = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002633 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2634 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07002635 goto done;
2636 default:
2637 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2638 __func__);
2639 return -EOPNOTSUPP;
2640
2641 }
2642
2643 }
2644 else
2645 {
2646 return -EOPNOTSUPP;
2647 }
2648
2649
2650 if(pRoamProfile)
2651 {
2652 if ( LastBSSType != pRoamProfile->BSSType )
2653 {
2654 /*interface type changed update in wiphy structure*/
2655 wdev->iftype = type;
2656
2657 /*the BSS mode changed, We need to issue disconnect
2658 if connected or in IBSS disconnect state*/
2659 if ( hdd_connGetConnectedBssType(
2660 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2661 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2662 {
2663 /*need to issue a disconnect to CSR.*/
2664 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2665 if( eHAL_STATUS_SUCCESS ==
2666 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2667 pAdapter->sessionId,
2668 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2669 {
2670 wait_for_completion_interruptible_timeout(
2671 &pAdapter->disconnect_comp_var,
2672 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2673 }
2674 }
2675 }
2676 }
2677
2678done:
2679 /*set bitmask based on updated value*/
2680 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
2681#ifdef WLAN_BTAMP_FEATURE
2682 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
2683 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2684 {
2685 //we are ok to do AMP
2686 pHddCtx->isAmpAllowed = VOS_TRUE;
2687 }
2688#endif //WLAN_BTAMP_FEATURE
2689 EXIT();
2690 return 0;
2691}
2692
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002693#ifdef FEATURE_WLAN_TDLS
2694static int wlan_hdd_tdls_add_station(struct wiphy *wiphy,
2695 struct net_device *dev, u8 *mac, bool update, tCsrStaParams *StaParams)
2696{
2697 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2698 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2699 VOS_STATUS status;
2700
2701 ENTER();
2702
2703 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
2704 {
2705 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2706 "Invalid arguments");
2707 return -EINVAL;
2708 }
Hoonki Lee27511902013-03-14 18:19:06 -07002709
2710 if ((eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) ||
2711 (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode))
2712 {
2713 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2714 "%s: TDLS mode is disabled OR not enabled in FW."
2715 MAC_ADDRESS_STR " Request declined.",
2716 __func__, MAC_ADDR_ARRAY(mac));
2717 return -ENOTSUPP;
2718 }
2719
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002720 if (pHddCtx->isLogpInProgress)
2721 {
2722 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2723 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07002724 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002725 return -EBUSY;
2726 }
2727
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002728 /* when self is on-going, we dont' want to change link_status */
2729 if ((0 == update) && wlan_hdd_tdls_is_peer_progress(pAdapter, mac))
2730 {
2731 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2732 "%s: " MAC_ADDRESS_STR
2733 " TDLS setup is ongoing. Request declined.",
2734 __func__, MAC_ADDR_ARRAY(mac));
2735 return -EPERM;
2736 }
2737
2738 /* when others are on-going, we want to change link_status to idle */
2739 if (wlan_hdd_tdls_is_progress(pAdapter, mac, TRUE))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002740 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002741 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2742 "%s: " MAC_ADDRESS_STR
2743 " TDLS setup is ongoing. Request declined.",
2744 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002745 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002746 }
2747
2748 /* first to check if we reached to maximum supported TDLS peer.
2749 TODO: for now, return -EPERM looks working fine,
2750 but need to check if any other errno fit into this category.*/
2751 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
2752 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002753 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2754 "%s: " MAC_ADDRESS_STR
2755 " TDLS Max peer already connected. Request declined.",
2756 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002757 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002758 }
2759 else
2760 {
2761 hddTdlsPeer_t *pTdlsPeer;
2762 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac);
2763 if (pTdlsPeer && (eTDLS_LINK_CONNECTED == pTdlsPeer->link_status))
2764 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002765 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2766 "%s: " MAC_ADDRESS_STR " already connected. Request declined.",
2767 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002768 return -EPERM;
2769 }
2770 }
2771
2772 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_CONNECTING);
2773
2774 INIT_COMPLETION(pAdapter->tdls_add_station_comp);
2775
2776 if (!update)
2777 {
2778 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
2779 pAdapter->sessionId, mac);
2780 }
2781 else
2782 {
2783 status = sme_ChangeTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
2784 pAdapter->sessionId, mac, StaParams);
2785 }
2786
2787 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_add_station_comp,
2788 msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
2789
2790 if (!status)
2791 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002792 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002793 "%s: timeout waiting for tdls add station indication",
2794 __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002795 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002796 }
2797 if ( eHAL_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus)
2798 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002799 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002800 "%s: Add Station is unsucessful", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002801 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002802 }
2803
2804 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07002805
2806error:
2807 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
2808 return -EPERM;
2809
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002810}
2811#endif
2812
Jeff Johnson295189b2012-06-20 16:38:30 -07002813static int wlan_hdd_change_station(struct wiphy *wiphy,
2814 struct net_device *dev,
2815 u8 *mac,
2816 struct station_parameters *params)
2817{
2818 VOS_STATUS status = VOS_STATUS_SUCCESS;
2819 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2820 v_MACADDR_t STAMacAddress;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002821#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002822 tCsrStaParams StaParams = {0};
2823 u32 set;
2824 tANI_U8 isBufSta = 0;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002825#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07002826 ENTER();
2827
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002828 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2829 {
2830 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2831 "%s:LOGP in Progress. Ignore!!!", __func__);
2832 return -EAGAIN;
2833 }
2834
Jeff Johnson295189b2012-06-20 16:38:30 -07002835 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
2836
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002837#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002838 StaParams.capability = params->capability;
2839 StaParams.uapsd_queues = params->uapsd_queues;
2840 StaParams.max_sp = params->max_sp;
2841
2842 if (0 != params->ext_capab_len)
2843 vos_mem_copy(StaParams.extn_capability, params->ext_capab,
2844 sizeof(StaParams.extn_capability));
2845
2846 if (NULL != params->ht_capa)
2847 vos_mem_copy(&StaParams.HTCap, params->ht_capa, sizeof(tSirHTCap));
2848
2849 StaParams.supported_rates_len = params->supported_rates_len;
2850
2851 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
2852 * The supported_rates array , for all the structures propogating till Add Sta
2853 * to the firmware has to be modified , if the supplicant (ieee80211) is
2854 * modified to send more rates.
2855 */
2856
2857 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
2858 */
2859 if (StaParams.supported_rates_len > SIR_MAC_MAX_SUPP_RATES)
2860 StaParams.supported_rates_len = SIR_MAC_MAX_SUPP_RATES;
2861
2862 if (0 != StaParams.supported_rates_len) {
2863 int i = 0;
2864 vos_mem_copy(StaParams.supported_rates, params->supported_rates,
2865 StaParams.supported_rates_len);
2866 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2867 "Supported Rates with Length %d", StaParams.supported_rates_len);
2868 for (i=0; i < StaParams.supported_rates_len; i++)
2869 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2870 "[%d]: %0x", i, StaParams.supported_rates[i]);
2871 }
2872
2873 if (NULL != params->vht_capa)
2874 vos_mem_copy(&StaParams.VHTCap, params->vht_capa, sizeof(tSirVHTCap));
2875
2876 set = params->sta_flags_set;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002877#endif
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002878
2879 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2880 || (pAdapter->device_mode == WLAN_HDD_P2P_GO))
Jeff Johnson295189b2012-06-20 16:38:30 -07002881 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002882 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
Jeff Johnson295189b2012-06-20 16:38:30 -07002883 {
2884 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
2885 WLANTL_STA_AUTHENTICATED);
2886
2887 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002888 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002889 return -EINVAL;
2890 }
2891 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002892#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002893 else if (pAdapter->device_mode == WLAN_HDD_INFRA_STATION ) {
2894 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
2895 if (0 != params->ext_capab_len ) {
2896 /*Define A Macro : TODO Sunil*/
2897 if ((1<<4) & StaParams.extn_capability[3]) {
2898 isBufSta = 1;
2899 }
2900 }
2901 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2902 "%s: TDLS Peer Parameters.", __func__);
2903 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2904 "uapsd_queues: %0x\n", params->uapsd_queues);
2905 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2906 "max_sp: %0x\n", params->max_sp);
2907 if (params->ht_capa) {
2908 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2909 "ht_capa->cap_info: %0x\n", params->ht_capa->cap_info);
2910 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2911 "ht_capa->ampdu_params_info: %0x\n",
2912 params->ht_capa->ampdu_params_info);
2913 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2914 "ht_capa->extended_capabilities: %0x\n",
2915 params->ht_capa->extended_ht_cap_info);
2916 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2917 "ht_capa->tx_BF_cap_info: %0x\n",
2918 params->ht_capa->tx_BF_cap_info);
2919 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2920 "ht_capa->antenna_selection_info: %0x\n",
2921 params->ht_capa->antenna_selection_info);
2922 }
2923 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2924 "params->capability: %0x\n",params->capability);
2925 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2926 "params->ext_capab_len: %0x\n",params->ext_capab_len);
2927 if (0 != params->ext_capab_len )
2928 {
2929 int i =0;
2930 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2931 "Extended capabilities:");
2932 for (i=0; i < params->ext_capab_len; i++)
2933 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2934 "[%d]: %0x", i, params->ext_capab[i]);
2935 }
2936 //status = wlan_hdd_tdls_set_peer_caps( mac, params->uapsd_queues,
2937 // params->max_sp, isBufSta);
2938 if (VOS_STATUS_SUCCESS != status) {
2939 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2940 "%s: wlan_hdd_tdls_set_peer_caps failed!", __func__);
2941 return -EINVAL;
2942 }
2943 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2944 "ht_capa->cap_info: %0x\n", StaParams.HTCap.capInfo);
2945 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 1, &StaParams);
2946
2947 if (VOS_STATUS_SUCCESS != status) {
2948 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2949 "%s: sme_ChangeTdlsPeerSta failed!", __func__);
2950 return -EINVAL;
2951 }
2952 }
2953 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002954#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002955
Jeff Johnsone7245742012-09-05 17:12:55 -07002956 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002957 return status;
2958}
2959
2960/*
2961 * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
2962 * This function is used to get peer station index in IBSS mode
2963 */
2964static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
2965{
2966 u8 idx = 0;
2967 u8 temp[VOS_MAC_ADDR_SIZE] = {0};
2968 ENTER();
2969 memset(temp, 0, VOS_MAC_ADDR_SIZE);
2970 for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
2971 {
2972 if ( (0 !=
2973 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
2974 && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
2975 temp, VOS_MAC_ADDR_SIZE)
2976 )
2977 {
2978 return idx;
2979 }
2980 }
2981 return idx;
2982}
2983
2984
2985/*
2986 * FUNCTION: wlan_hdd_cfg80211_add_key
2987 * This function is used to initialize the key information
2988 */
2989#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2990static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2991 struct net_device *ndev,
2992 u8 key_index, bool pairwise,
2993 const u8 *mac_addr,
2994 struct key_params *params
2995 )
2996#else
2997static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2998 struct net_device *ndev,
2999 u8 key_index, const u8 *mac_addr,
3000 struct key_params *params
3001 )
3002#endif
3003{
3004 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3005 tCsrRoamSetKey setKey;
3006 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3007 int status = 0;
3008 v_U32_t roamId= 0xFF;
3009 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
3010 hdd_hostapd_state_t *pHostapdState;
3011 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003012 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07003013
3014 ENTER();
3015
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003016 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3017 {
3018 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3019 "%s:LOGP in Progress. Ignore!!!", __func__);
3020 return -EAGAIN;
3021 }
3022
Jeff Johnson295189b2012-06-20 16:38:30 -07003023 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3024 __func__,pAdapter->device_mode);
3025
3026 if (CSR_MAX_NUM_KEY <= key_index)
3027 {
3028 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3029 key_index);
3030
3031 return -EINVAL;
3032 }
3033
3034 hddLog(VOS_TRACE_LEVEL_INFO,
3035 "%s: called with key index = %d & key length %d",
3036 __func__, key_index, params->key_len);
3037
3038 /*extract key idx, key len and key*/
3039 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3040 setKey.keyId = key_index;
3041 setKey.keyLength = params->key_len;
3042 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
3043
3044 switch (params->cipher)
3045 {
3046 case WLAN_CIPHER_SUITE_WEP40:
3047 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
3048 break;
3049
3050 case WLAN_CIPHER_SUITE_WEP104:
3051 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
3052 break;
3053
3054 case WLAN_CIPHER_SUITE_TKIP:
3055 {
3056 u8 *pKey = &setKey.Key[0];
3057 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
3058
3059 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
3060
3061 /*Supplicant sends the 32bytes key in this order
3062
3063 |--------------|----------|----------|
3064 | Tk1 |TX-MIC | RX Mic |
3065 |--------------|----------|----------|
3066 <---16bytes---><--8bytes--><--8bytes-->
3067
3068 */
3069 /*Sme expects the 32 bytes key to be in the below order
3070
3071 |--------------|----------|----------|
3072 | Tk1 |RX-MIC | TX Mic |
3073 |--------------|----------|----------|
3074 <---16bytes---><--8bytes--><--8bytes-->
3075 */
3076 /* Copy the Temporal Key 1 (TK1) */
3077 vos_mem_copy(pKey, params->key,16);
3078
3079 /*Copy the rx mic first*/
3080 vos_mem_copy(&pKey[16],&params->key[24],8);
3081
3082 /*Copy the tx mic */
3083 vos_mem_copy(&pKey[24],&params->key[16],8);
3084
3085
3086 break;
3087 }
3088
3089 case WLAN_CIPHER_SUITE_CCMP:
3090 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
3091 break;
3092
3093#ifdef FEATURE_WLAN_WAPI
3094 case WLAN_CIPHER_SUITE_SMS4:
3095 {
3096 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3097 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
3098 params->key, params->key_len);
3099 return 0;
3100 }
3101#endif
3102#ifdef FEATURE_WLAN_CCX
3103 case WLAN_CIPHER_SUITE_KRK:
3104 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
3105 break;
3106#endif
3107 default:
3108 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
3109 __func__, params->cipher);
3110 return -EOPNOTSUPP;
3111 }
3112
3113 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
3114 __func__, setKey.encType);
3115
3116
3117
3118 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003119 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07003120 )
3121 {
3122
3123
3124 if (
3125#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3126 (!pairwise)
3127#else
3128 (!mac_addr || is_broadcast_ether_addr(mac_addr))
3129#endif
3130 )
3131 {
3132 /* set group key*/
3133 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson1250df42012-12-10 14:31:52 -08003134 "%s- %d: setting Broadcast key",
Jeff Johnson295189b2012-06-20 16:38:30 -07003135 __func__, __LINE__);
3136 setKey.keyDirection = eSIR_RX_ONLY;
3137 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3138 }
3139 else
3140 {
3141 /* set pairwise key*/
3142 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3143 "%s- %d: setting pairwise key",
3144 __func__, __LINE__);
3145 setKey.keyDirection = eSIR_TX_RX;
3146 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3147 }
3148
3149 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3150 if( pHostapdState->bssState == BSS_START )
3151 {
3152 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3153
3154 if ( status != eHAL_STATUS_SUCCESS )
3155 {
3156 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3157 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3158 __LINE__, status );
3159 }
3160 }
3161
3162 /* Saving WEP keys */
3163 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
3164 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
3165 {
3166 //Save the wep key in ap context. Issue setkey after the BSS is started.
3167 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3168 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
3169 }
3170 else
3171 {
3172 //Save the key in ap context. Issue setkey after the BSS is started.
3173 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3174 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
3175 }
3176 }
3177 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003178 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003179 )
3180 {
3181 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3182 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3183
3184 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
3185
Venkata Prathyusha Kuntupalliee2ce712013-01-17 14:09:24 -08003186 pWextState->roamProfile.Keys.defaultIndex = key_index;
3187
3188
Jeff Johnson295189b2012-06-20 16:38:30 -07003189 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
3190 params->key, params->key_len);
3191
3192 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3193
3194 if (!( ( IW_AUTH_KEY_MGMT_802_1X
3195 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
3196 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3197 )
3198 &&
3199 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3200 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3201 )
3202 )
3203 {
3204 /* in case of static WEP, macaddr/bssid is not coming from nl80211
3205 * interface, copy bssid for pairwise key and group macaddr for
3206 * group key initialization*/
3207
3208 tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
3209
3210 pWextState->roamProfile.negotiatedUCEncryptionType =
3211 pHddStaCtx->conn_info.ucEncryptionType =
3212 ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
3213 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
3214 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
3215
3216
3217 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3218 "%s: Negotiated encryption type %d", __func__,
3219 pWextState->roamProfile.negotiatedUCEncryptionType);
3220
3221 sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
3222 &pWextState->roamProfile, true);
3223 setKey.keyLength = 0;
3224 setKey.keyDirection = eSIR_TX_RX;
3225
3226#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3227 if (pairwise)
3228 {
3229#endif
3230 if (mac_addr)
3231 {
3232 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3233 }
3234 else
3235 {
3236 /* macaddr is NULL, set the peerMac to bssId in case of BSS,
3237 * and peerMacAddress in case of IBSS*/
3238 if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
3239 {
3240 u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
3241 if (HDD_MAX_NUM_IBSS_STA != staidx)
3242 {
3243 vos_mem_copy(setKey.peerMac,
3244 &pHddStaCtx->conn_info.peerMacAddress[staidx],
3245 WNI_CFG_BSSID_LEN);
3246
3247 }
3248 else
3249 {
3250 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
3251 __func__);
3252 return -EOPNOTSUPP;
3253 }
3254 }
3255 else
3256 {
3257 vos_mem_copy(setKey.peerMac,
3258 &pHddStaCtx->conn_info.bssId[0],
3259 WNI_CFG_BSSID_LEN);
3260 }
3261 }
3262#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3263 }
3264 else
3265 {
3266 /* set group key*/
3267 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3268 "%s- %d: setting Group key",
3269 __func__, __LINE__);
3270 setKey.keyDirection = eSIR_RX_ONLY;
3271 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3272 }
3273#endif
3274 }
3275 else if (
3276#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3277 (!pairwise)
3278#else
3279 (!mac_addr || is_broadcast_ether_addr(mac_addr))
3280#endif
3281 )
3282 {
3283 /* set group key*/
3284 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3285 "%s- %d: setting Group key",
3286 __func__, __LINE__);
3287 setKey.keyDirection = eSIR_RX_ONLY;
3288 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3289 }
3290 else
3291 {
3292 /* set pairwise key*/
3293 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3294 "%s- %d: setting pairwise key",
3295 __func__, __LINE__);
3296 setKey.keyDirection = eSIR_TX_RX;
3297 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3298 }
3299
3300 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3301 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3302 __func__, setKey.peerMac[0], setKey.peerMac[1],
3303 setKey.peerMac[2], setKey.peerMac[3],
3304 setKey.peerMac[4], setKey.peerMac[5],
3305 setKey.keyDirection);
3306
3307 vos_status = wlan_hdd_check_ula_done(pAdapter);
3308
3309 if ( vos_status != VOS_STATUS_SUCCESS )
3310 {
3311 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3312 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
3313 __LINE__, vos_status );
3314
3315 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3316
3317 return -EINVAL;
3318
3319 }
3320
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003321#ifdef WLAN_FEATURE_VOWIFI_11R
3322 /* The supplicant may attempt to set the PTK once pre-authentication is done.
3323 Save the key in the UMAC and include it in the ADD BSS request */
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003324 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303325 if( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_WAIT )
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003326 {
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303327 return -EINVAL;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003328 }
3329#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07003330
3331 /* issue set key request to SME*/
3332 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3333 pAdapter->sessionId, &setKey, &roamId );
3334
3335 if ( 0 != status )
3336 {
3337 hddLog(VOS_TRACE_LEVEL_ERROR,
3338 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3339 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3340 return -EINVAL;
3341 }
3342
3343
3344 /* in case of IBSS as there was no information available about WEP keys during
3345 * IBSS join, group key intialized with NULL key, so re-initialize group key
3346 * with correct value*/
3347 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
3348 !( ( IW_AUTH_KEY_MGMT_802_1X
3349 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
3350 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3351 )
3352 &&
3353 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3354 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3355 )
3356 )
3357 {
3358 setKey.keyDirection = eSIR_RX_ONLY;
3359 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3360
3361 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3362 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3363 __func__, setKey.peerMac[0], setKey.peerMac[1],
3364 setKey.peerMac[2], setKey.peerMac[3],
3365 setKey.peerMac[4], setKey.peerMac[5],
3366 setKey.keyDirection);
3367
3368 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3369 pAdapter->sessionId, &setKey, &roamId );
3370
3371 if ( 0 != status )
3372 {
3373 hddLog(VOS_TRACE_LEVEL_ERROR,
3374 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
3375 __func__, status);
3376 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3377 return -EINVAL;
3378 }
3379 }
3380 }
3381
3382 return 0;
3383}
3384
3385/*
3386 * FUNCTION: wlan_hdd_cfg80211_get_key
3387 * This function is used to get the key information
3388 */
3389#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3390static int wlan_hdd_cfg80211_get_key(
3391 struct wiphy *wiphy,
3392 struct net_device *ndev,
3393 u8 key_index, bool pairwise,
3394 const u8 *mac_addr, void *cookie,
3395 void (*callback)(void *cookie, struct key_params*)
3396 )
3397#else
3398static int wlan_hdd_cfg80211_get_key(
3399 struct wiphy *wiphy,
3400 struct net_device *ndev,
3401 u8 key_index, const u8 *mac_addr, void *cookie,
3402 void (*callback)(void *cookie, struct key_params*)
3403 )
3404#endif
3405{
3406 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3407 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3408 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
3409 struct key_params params;
3410
3411 ENTER();
3412
3413 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3414 __func__,pAdapter->device_mode);
3415
3416 memset(&params, 0, sizeof(params));
3417
3418 if (CSR_MAX_NUM_KEY <= key_index)
3419 {
3420 return -EINVAL;
3421 }
3422
3423 switch(pRoamProfile->EncryptionType.encryptionType[0])
3424 {
3425 case eCSR_ENCRYPT_TYPE_NONE:
3426 params.cipher = IW_AUTH_CIPHER_NONE;
3427 break;
3428
3429 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3430 case eCSR_ENCRYPT_TYPE_WEP40:
3431 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3432 break;
3433
3434 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3435 case eCSR_ENCRYPT_TYPE_WEP104:
3436 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3437 break;
3438
3439 case eCSR_ENCRYPT_TYPE_TKIP:
3440 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3441 break;
3442
3443 case eCSR_ENCRYPT_TYPE_AES:
3444 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3445 break;
3446
3447 default:
3448 params.cipher = IW_AUTH_CIPHER_NONE;
3449 break;
3450 }
3451
3452 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3453 params.seq_len = 0;
3454 params.seq = NULL;
3455 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3456 callback(cookie, &params);
3457 return 0;
3458}
3459
3460/*
3461 * FUNCTION: wlan_hdd_cfg80211_del_key
3462 * This function is used to delete the key information
3463 */
3464#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3465static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3466 struct net_device *ndev,
3467 u8 key_index,
3468 bool pairwise,
3469 const u8 *mac_addr
3470 )
3471#else
3472static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3473 struct net_device *ndev,
3474 u8 key_index,
3475 const u8 *mac_addr
3476 )
3477#endif
3478{
3479 int status = 0;
3480
3481 //This code needs to be revisited. There is sme_removeKey API, we should
3482 //plan to use that. After the change to use correct index in setkey,
3483 //it is observed that this is invalidating peer
3484 //key index whenever re-key is done. This is affecting data link.
3485 //It should be ok to ignore del_key.
3486#if 0
3487 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3488 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
3489 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3490 tCsrRoamSetKey setKey;
3491 v_U32_t roamId= 0xFF;
3492
3493 ENTER();
3494
3495 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3496 __func__,pAdapter->device_mode);
3497
3498 if (CSR_MAX_NUM_KEY <= key_index)
3499 {
3500 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3501 key_index);
3502
3503 return -EINVAL;
3504 }
3505
3506 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3507 setKey.keyId = key_index;
3508
3509 if (mac_addr)
3510 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3511 else
3512 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3513
3514 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3515
3516 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003517 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07003518 )
3519 {
3520
3521 hdd_hostapd_state_t *pHostapdState =
3522 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3523 if( pHostapdState->bssState == BSS_START)
3524 {
3525 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3526
3527 if ( status != eHAL_STATUS_SUCCESS )
3528 {
3529 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3530 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3531 __LINE__, status );
3532 }
3533 }
3534 }
3535 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003536 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003537 )
3538 {
3539 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3540
3541 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3542
3543 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3544 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
3545 __func__, setKey.peerMac[0], setKey.peerMac[1],
3546 setKey.peerMac[2], setKey.peerMac[3],
3547 setKey.peerMac[4], setKey.peerMac[5]);
3548 if(pAdapter->sessionCtx.station.conn_info.connState ==
3549 eConnectionState_Associated)
3550 {
3551 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3552 pAdapter->sessionId, &setKey, &roamId );
3553
3554 if ( 0 != status )
3555 {
3556 hddLog(VOS_TRACE_LEVEL_ERROR,
3557 "%s: sme_RoamSetKey failure, returned %d",
3558 __func__, status);
3559 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3560 return -EINVAL;
3561 }
3562 }
3563 }
3564#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003565 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003566 return status;
3567}
3568
3569/*
3570 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3571 * This function is used to set the default tx key index
3572 */
3573#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3574static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3575 struct net_device *ndev,
3576 u8 key_index,
3577 bool unicast, bool multicast)
3578#else
3579static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3580 struct net_device *ndev,
3581 u8 key_index)
3582#endif
3583{
3584 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3585 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3586 int status = 0;
3587 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3588
3589 ENTER();
3590
3591 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3592 __func__,pAdapter->device_mode, key_index);
3593
3594 if (CSR_MAX_NUM_KEY <= key_index)
3595 {
3596 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3597 key_index);
3598
3599 return -EINVAL;
3600 }
3601
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003602 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3603 {
3604 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3605 "%s:LOGP in Progress. Ignore!!!", __func__);
3606 return -EAGAIN;
3607 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003608
3609 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003610 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003611 )
3612 {
3613 if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
3614 (eCSR_ENCRYPT_TYPE_TKIP !=
3615 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3616 (eCSR_ENCRYPT_TYPE_AES !=
3617 pWextState->roamProfile.EncryptionType.encryptionType[0])
3618 )
3619 {
3620 /* if default key index is not same as previous one,
3621 * then update the default key index */
3622
3623 tCsrRoamSetKey setKey;
3624 v_U32_t roamId= 0xFF;
3625 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
3626
3627 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
3628 __func__, key_index);
3629
3630 Keys->defaultIndex = (u8)key_index;
3631 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3632 setKey.keyId = key_index;
3633 setKey.keyLength = Keys->KeyLength[key_index];
3634
3635 vos_mem_copy(&setKey.Key[0],
3636 &Keys->KeyMaterial[key_index][0],
3637 Keys->KeyLength[key_index]);
3638
3639 setKey.keyDirection = eSIR_TX_ONLY;
3640
3641 vos_mem_copy(setKey.peerMac,
3642 &pHddStaCtx->conn_info.bssId[0],
3643 WNI_CFG_BSSID_LEN);
3644
3645 setKey.encType =
3646 pWextState->roamProfile.EncryptionType.encryptionType[0];
3647
3648 /* issue set key request */
3649 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3650 pAdapter->sessionId, &setKey, &roamId );
3651
3652 if ( 0 != status )
3653 {
3654 hddLog(VOS_TRACE_LEVEL_ERROR,
3655 "%s: sme_RoamSetKey failed, returned %d", __func__,
3656 status);
3657 return -EINVAL;
3658 }
3659 }
3660 }
3661
3662 /* In SoftAp mode setting key direction for default mode */
3663 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3664 {
3665 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3666 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3667 (eCSR_ENCRYPT_TYPE_AES !=
3668 pWextState->roamProfile.EncryptionType.encryptionType[0])
3669 )
3670 {
3671 /* Saving key direction for default key index to TX default */
3672 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3673 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3674 }
3675 }
3676
3677 return status;
3678}
3679
Jeff Johnson295189b2012-06-20 16:38:30 -07003680/*
3681 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3682 * This function is used to inform the BSS details to nl80211 interface.
3683 */
3684static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3685 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3686{
3687 struct net_device *dev = pAdapter->dev;
3688 struct wireless_dev *wdev = dev->ieee80211_ptr;
3689 struct wiphy *wiphy = wdev->wiphy;
3690 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3691 int chan_no;
3692 int ie_length;
3693 const char *ie;
3694 unsigned int freq;
3695 struct ieee80211_channel *chan;
3696 int rssi = 0;
3697 struct cfg80211_bss *bss = NULL;
3698
3699 ENTER();
3700
3701 if( NULL == pBssDesc )
3702 {
3703 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3704 return bss;
3705 }
3706
3707 chan_no = pBssDesc->channelId;
3708 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3709 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3710
3711 if( NULL == ie )
3712 {
3713 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3714 return bss;
3715 }
3716
3717#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3718 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3719 {
3720 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3721 }
3722 else
3723 {
3724 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3725 }
3726#else
3727 freq = ieee80211_channel_to_frequency(chan_no);
3728#endif
3729
3730 chan = __ieee80211_get_channel(wiphy, freq);
3731
3732 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3733 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3734 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3735 if (bss == NULL)
3736 {
3737 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3738
3739 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3740 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3741 pBssDesc->capabilityInfo,
3742 pBssDesc->beaconInterval, ie, ie_length,
3743 rssi, GFP_KERNEL ));
3744}
3745 else
3746 {
3747 return bss;
3748 }
3749}
3750
3751
3752
3753/*
3754 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3755 * This function is used to inform the BSS details to nl80211 interface.
3756 */
3757struct cfg80211_bss*
3758wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3759 tSirBssDescription *bss_desc
3760 )
3761{
3762 /*
3763 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3764 already exists in bss data base of cfg80211 for that particular BSS ID.
3765 Using cfg80211_inform_bss_frame to update the bss entry instead of
3766 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3767 now there is no possibility to get the mgmt(probe response) frame from PE,
3768 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3769 cfg80211_inform_bss_frame.
3770 */
3771 struct net_device *dev = pAdapter->dev;
3772 struct wireless_dev *wdev = dev->ieee80211_ptr;
3773 struct wiphy *wiphy = wdev->wiphy;
3774 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003775#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3776 qcom_ie_age *qie_age = NULL;
3777 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3778#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003779 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003780#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003781 const char *ie =
3782 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3783 unsigned int freq;
3784 struct ieee80211_channel *chan;
3785 struct ieee80211_mgmt *mgmt =
3786 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3787 struct cfg80211_bss *bss_status = NULL;
3788 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3789 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003790#ifdef WLAN_OPEN_SOURCE
3791 struct timespec ts;
3792#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003793
3794 ENTER();
3795
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003796 if (!mgmt)
3797 return NULL;
3798
Jeff Johnson295189b2012-06-20 16:38:30 -07003799 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003800
3801#ifdef WLAN_OPEN_SOURCE
3802 /* Android does not want the timestamp from the frame.
3803 Instead it wants a monotonic increasing value */
3804 get_monotonic_boottime(&ts);
3805 mgmt->u.probe_resp.timestamp =
3806 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3807#else
3808 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003809 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3810 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003811
3812#endif
3813
Jeff Johnson295189b2012-06-20 16:38:30 -07003814 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3815 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003816
3817#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3818 /* GPS Requirement: need age ie per entry. Using vendor specific. */
3819 /* Assuming this is the last IE, copy at the end */
3820 ie_length -=sizeof(qcom_ie_age);
3821 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
3822 qie_age->element_id = QCOM_VENDOR_IE_ID;
3823 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
3824 qie_age->oui_1 = QCOM_OUI1;
3825 qie_age->oui_2 = QCOM_OUI2;
3826 qie_age->oui_3 = QCOM_OUI3;
3827 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
3828 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
3829#endif
3830
Jeff Johnson295189b2012-06-20 16:38:30 -07003831 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3832
3833 mgmt->frame_control |=
3834 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3835
3836#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3837 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3838 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3839 {
3840 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3841 }
3842 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3843 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3844
3845 {
3846 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3847 }
3848 else
3849 {
3850 kfree(mgmt);
3851 return NULL;
3852 }
3853#else
3854 freq = ieee80211_channel_to_frequency(chan_no);
3855#endif
3856 chan = __ieee80211_get_channel(wiphy, freq);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08003857 /*when the band is changed on the fly using the GUI, three things are done
3858 * 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)
3859 * as part of the scan abort, message willbe queued to PE and we proceed with flushing and changinh the band.
3860 * pe will stop the scanning further and report back the results what ever it had till now by calling the call back function.
3861 * if the time between update band and scandone call back is sufficent enough the band change reflects in SME, SME validates the channels
3862 * and discards the channels correponding to previous band and calls back with zero bss results.
3863 * 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
3864 * all the channels correponding to previous band.this is due to race condition.but those channels are invalid to the new band and so
3865 * this function __ieee80211_get_channel will return NULL.Each time we report scan result with this pointer null warning kernel trace is printed.
3866 * if the scan results contain large number of APs continuosly kernel warning trace is printed and it will lead to apps watch dog bark.
3867 * So drop the bss and continue to next bss.
3868 */
3869 if(chan == NULL)
3870 {
3871 hddLog(VOS_TRACE_LEVEL_INFO, "%s chan pointer is NULL", __func__);
3872 return NULL;
3873 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003874 /*To keep the rssi icon of the connected AP in the scan window
3875 *and the rssi icon of the wireless networks in sync
3876 * */
3877 if (( eConnectionState_Associated ==
3878 pAdapter->sessionCtx.station.conn_info.connState ) &&
3879 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3880 pAdapter->sessionCtx.station.conn_info.bssId,
3881 WNI_CFG_BSSID_LEN)))
3882 {
3883 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3884 rssi = (pAdapter->rssi * 100);
3885 }
3886 else
3887 {
3888 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3889 }
3890
3891 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3892 frame_len, rssi, GFP_KERNEL);
3893 kfree(mgmt);
3894 return bss_status;
3895}
3896
3897/*
3898 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3899 * This function is used to update the BSS data base of CFG8011
3900 */
3901struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3902 tCsrRoamInfo *pRoamInfo
3903 )
3904{
3905 tCsrRoamConnectedProfile roamProfile;
3906 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3907 struct cfg80211_bss *bss = NULL;
3908
3909 ENTER();
3910
3911 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
3912 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
3913
3914 if (NULL != roamProfile.pBssDesc)
3915 {
3916 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
3917 &roamProfile);
3918
3919 if (NULL == bss)
3920 {
3921 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
3922 __func__);
3923 }
3924
3925 sme_RoamFreeConnectProfile(hHal, &roamProfile);
3926 }
3927 else
3928 {
3929 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
3930 __func__);
3931 }
3932 return bss;
3933}
3934
3935/*
3936 * FUNCTION: wlan_hdd_cfg80211_update_bss
3937 */
3938static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
3939 hdd_adapter_t *pAdapter
3940 )
3941{
3942 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3943 tCsrScanResultInfo *pScanResult;
3944 eHalStatus status = 0;
3945 tScanResultHandle pResult;
3946 struct cfg80211_bss *bss_status = NULL;
3947
3948 ENTER();
3949
3950 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3951 {
3952 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3953 return -EAGAIN;
3954 }
3955
3956 /*
3957 * start getting scan results and populate cgf80211 BSS database
3958 */
3959 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
3960
3961 /* no scan results */
3962 if (NULL == pResult)
3963 {
3964 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
3965 return status;
3966 }
3967
3968 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
3969
3970 while (pScanResult)
3971 {
3972 /*
3973 * cfg80211_inform_bss() is not updating ie field of bss entry, if
3974 * entry already exists in bss data base of cfg80211 for that
3975 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
3976 * bss entry instead of cfg80211_inform_bss, But this call expects
3977 * mgmt packet as input. As of now there is no possibility to get
3978 * the mgmt(probe response) frame from PE, converting bss_desc to
3979 * ieee80211_mgmt(probe response) and passing to c
3980 * fg80211_inform_bss_frame.
3981 * */
3982
3983 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
3984 &pScanResult->BssDescriptor);
3985
3986
3987 if (NULL == bss_status)
3988 {
3989 hddLog(VOS_TRACE_LEVEL_INFO,
3990 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
3991 }
3992 else
3993 {
3994 cfg80211_put_bss(bss_status);
3995 }
3996
3997 pScanResult = sme_ScanResultGetNext(hHal, pResult);
3998 }
3999
4000 sme_ScanResultPurge(hHal, pResult);
4001
4002 return 0;
4003}
4004
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004005void
4006hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
4007{
4008 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004009 "%02X:%02X:%02X:%02X:%02X:%02X\n",
4010 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
4011 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004012} /****** end hddPrintMacAddr() ******/
4013
4014void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004015hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004016{
4017 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004018 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
4019 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
4020 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
4021 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004022} /****** end hddPrintPmkId() ******/
4023
4024//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
4025//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
4026
4027//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
4028//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
4029
4030#define dump_bssid(bssid) \
4031 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004032 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
4033 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
4034 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004035 }
4036
4037#define dump_pmkid(pMac, pmkid) \
4038 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004039 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
4040 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
4041 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004042 }
4043
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07004044#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004045/*
4046 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
4047 * This function is used to notify the supplicant of a new PMKSA candidate.
4048 */
4049int wlan_hdd_cfg80211_pmksa_candidate_notify(
4050 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
4051 int index, bool preauth )
4052{
Jeff Johnsone7245742012-09-05 17:12:55 -07004053#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004054 struct net_device *dev = pAdapter->dev;
4055
4056 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07004057 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004058
4059 if( NULL == pRoamInfo )
4060 {
4061 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
4062 return -EINVAL;
4063 }
4064
4065 dump_bssid(pRoamInfo->bssid);
4066 cfg80211_pmksa_candidate_notify(dev, index,
4067 pRoamInfo->bssid, preauth, GFP_KERNEL);
Jeff Johnsone7245742012-09-05 17:12:55 -07004068#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004069 return 0;
4070}
4071#endif //FEATURE_WLAN_LFR
4072
Jeff Johnson295189b2012-06-20 16:38:30 -07004073/*
4074 * FUNCTION: hdd_cfg80211_scan_done_callback
4075 * scanning callback function, called after finishing scan
4076 *
4077 */
4078static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
4079 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
4080{
4081 struct net_device *dev = (struct net_device *) pContext;
4082 //struct wireless_dev *wdev = dev->ieee80211_ptr;
4083 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004084 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4085 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004086 struct cfg80211_scan_request *req = NULL;
4087 int ret = 0;
4088
4089 ENTER();
4090
4091 hddLog(VOS_TRACE_LEVEL_INFO,
4092 "%s called with halHandle = %p, pContext = %p,"
4093 "scanID = %d, returned status = %d\n",
4094 __func__, halHandle, pContext, (int) scanId, (int) status);
4095
4096 //Block on scan req completion variable. Can't wait forever though.
4097 ret = wait_for_completion_interruptible_timeout(
4098 &pScanInfo->scan_req_completion_event,
4099 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
4100 if (!ret)
4101 {
4102 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004103 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004104 }
4105
4106 if(pScanInfo->mScanPending != VOS_TRUE)
4107 {
4108 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004109 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004110 }
4111
4112 /* Check the scanId */
4113 if (pScanInfo->scanId != scanId)
4114 {
4115 hddLog(VOS_TRACE_LEVEL_INFO,
4116 "%s called with mismatched scanId pScanInfo->scanId = %d "
4117 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
4118 (int) scanId);
4119 }
4120
Jeff Johnson295189b2012-06-20 16:38:30 -07004121 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
4122 pAdapter);
4123
4124 if (0 > ret)
4125 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
4126
4127
4128 /* If any client wait scan result through WEXT
4129 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004130 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07004131 {
4132 /* The other scan request waiting for current scan finish
4133 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004134 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004135 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004136 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004137 }
4138 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004139 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004140 {
4141 struct net_device *dev = pAdapter->dev;
4142 union iwreq_data wrqu;
4143 int we_event;
4144 char *msg;
4145
4146 memset(&wrqu, '\0', sizeof(wrqu));
4147 we_event = SIOCGIWSCAN;
4148 msg = NULL;
4149 wireless_send_event(dev, we_event, &wrqu, msg);
4150 }
4151 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004152 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004153
4154 /* Get the Scan Req */
4155 req = pAdapter->request;
4156
4157 if (!req)
4158 {
4159 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004160 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07004161 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004162 }
4163
4164 /*
4165 * setting up 0, just in case.
4166 */
4167 req->n_ssids = 0;
4168 req->n_channels = 0;
4169 req->ie = 0;
4170
Jeff Johnson295189b2012-06-20 16:38:30 -07004171 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004172 /* Scan is no longer pending */
4173 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004174
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07004175 /*
4176 * cfg80211_scan_done informing NL80211 about completion
4177 * of scanning
4178 */
4179 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004180 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004181
Jeff Johnsone7245742012-09-05 17:12:55 -07004182allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004183 /* release the wake lock at the end of the scan*/
4184 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004185
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004186 /* Acquire wakelock to handle the case where APP's tries to suspend
4187 * immediatly after the driver gets connect request(i.e after scan)
4188 * from supplicant, this result in app's is suspending and not able
4189 * to process the connect request to AP */
4190 hdd_allow_suspend_timeout(100);
4191
Jeff Johnson295189b2012-06-20 16:38:30 -07004192 EXIT();
4193 return 0;
4194}
4195
4196/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004197 * FUNCTION: hdd_isScanAllowed
4198 * Go through each adapter and check if scan allowed
4199 *
4200 */
4201v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
4202{
4203 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4204 hdd_station_ctx_t *pHddStaCtx = NULL;
4205 hdd_adapter_t *pAdapter = NULL;
4206 VOS_STATUS status = 0;
4207 v_U8_t staId = 0;
4208 v_U8_t *staMac = NULL;
4209
4210 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4211
4212 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4213 {
4214 pAdapter = pAdapterNode->pAdapter;
4215
4216 if( pAdapter )
4217 {
4218 hddLog(VOS_TRACE_LEVEL_INFO,
4219 "%s: Adapter with device mode %d exists",
4220 __func__, pAdapter->device_mode);
4221 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4222 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4223 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
4224 {
4225 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4226 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
4227 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
4228 {
4229 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
4230 hddLog(VOS_TRACE_LEVEL_ERROR,
4231 "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the "
4232 "middle of WPS/EAPOL exchange.", __func__,
4233 staMac[0], staMac[1], staMac[2],
4234 staMac[3], staMac[4], staMac[5]);
4235 return VOS_FALSE;
4236 }
4237 }
4238 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
4239 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
4240 {
4241 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
4242 {
4243 if ((pAdapter->aStaInfo[staId].isUsed) &&
4244 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
4245 {
4246 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
4247
4248 hddLog(VOS_TRACE_LEVEL_ERROR,
4249 "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the "
4250 "middle of WPS/EAPOL exchange.", __func__,
4251 staMac[0], staMac[1], staMac[2],
4252 staMac[3], staMac[4], staMac[5]);
4253 return VOS_FALSE;
4254 }
4255 }
4256 }
4257 }
4258 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4259 pAdapterNode = pNext;
4260 }
4261 hddLog(VOS_TRACE_LEVEL_INFO,
4262 "%s: Scan allowed", __func__);
4263 return VOS_TRUE;
4264}
4265
4266/*
Jeff Johnson295189b2012-06-20 16:38:30 -07004267 * FUNCTION: wlan_hdd_cfg80211_scan
4268 * this scan respond to scan trigger and update cfg80211 scan database
4269 * later, scan dump command can be used to recieve scan results
4270 */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08004271int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
4272#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4273 struct net_device *dev,
4274#endif
4275 struct cfg80211_scan_request *request)
4276{
4277#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4278 struct net_device *dev = request->wdev->netdev;
4279#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004280 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4281 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4282 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4283 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
4284 tCsrScanRequest scanRequest;
4285 tANI_U8 *channelList = NULL, i;
4286 v_U32_t scanId = 0;
4287 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004288 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004289 v_U8_t* pP2pIe = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004290
4291 ENTER();
4292
4293 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4294 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004295
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004296 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004297 (eConnectionState_Connecting ==
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004298 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004299 {
4300 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004301 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
4302 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004303 return -EBUSY;
4304 }
4305
Jeff Johnson295189b2012-06-20 16:38:30 -07004306#ifdef WLAN_BTAMP_FEATURE
4307 //Scan not supported when AMP traffic is on.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004308 if (VOS_TRUE == WLANBAP_AmpSessionOn())
Jeff Johnson295189b2012-06-20 16:38:30 -07004309 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004310 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004311 "%s: No scanning when AMP is on", __func__);
4312 return -EOPNOTSUPP;
4313 }
4314#endif
4315 //Scan on any other interface is not supported.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004316 if (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07004317 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004318 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004319 "%s: Not scanning on device_mode = %d",
4320 __func__, pAdapter->device_mode);
4321 return -EOPNOTSUPP;
4322 }
4323
4324 if (TRUE == pScanInfo->mScanPending)
4325 {
4326 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004327 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07004328 }
4329
4330 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4331 {
4332 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4333 "%s:LOGP in Progress. Ignore!!!", __func__);
4334 return -EAGAIN;
4335 }
4336
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07004337 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
4338 {
4339 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4340 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
4341 return -EAGAIN;
4342 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004343 //Don't Allow Scan and return busy if Remain On
4344 //Channel and action frame is pending
4345 //Otherwise Cancel Remain On Channel and allow Scan
4346 //If no action frame pending
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004347 if (0 != wlan_hdd_check_remain_on_channel(pAdapter))
Jeff Johnson32d95a32012-09-10 13:15:23 -07004348 {
4349 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
4350 return -EBUSY;
4351 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004352#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkalac3c42b92013-03-20 19:42:34 -07004353 if (wlan_hdd_tdlsConnectedPeers(pAdapter))
Hoonki Lee93e67ff2013-03-19 15:49:25 -07004354 {
Gopichand Nakkalac3c42b92013-03-20 19:42:34 -07004355 tANI_U8 staIdx;
4356
4357 for (staIdx = 0; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
4358 {
4359 if (pHddCtx->tdlsConnInfo[staIdx].staId)
4360 {
4361 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4362 ("scan: indicate TDLS teadown (staId %d)"), pHddCtx->tdlsConnInfo[staIdx].staId);
4363 }
4364#ifdef CONFIG_TDLS_IMPLICIT
4365 cfg80211_tdls_oper_request(pAdapter->dev,
4366 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes,
4367 NL80211_TDLS_TEARDOWN,
4368 eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON,
4369 GFP_KERNEL);
4370#endif
4371 }
4372 return -EBUSY;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004373 }
Gopichand Nakkalac3c42b92013-03-20 19:42:34 -07004374
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004375#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07004376
Jeff Johnson295189b2012-06-20 16:38:30 -07004377 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
4378 {
4379 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08004380 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004381 return -EAGAIN;
4382 }
4383 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
4384 {
4385 hddLog(VOS_TRACE_LEVEL_WARN,
4386 "%s: MAX TM Level Scan not allowed", __func__);
4387 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4388 return -EBUSY;
4389 }
4390 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4391
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004392 /* Check if scan is allowed at this point of time.
4393 */
4394 if (!hdd_isScanAllowed(pHddCtx))
4395 {
4396 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
4397 return -EBUSY;
4398 }
4399
Jeff Johnson295189b2012-06-20 16:38:30 -07004400 vos_mem_zero( &scanRequest, sizeof(scanRequest));
4401
4402 if (NULL != request)
4403 {
4404 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
4405 (int)request->n_ssids);
4406
4407 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
4408 * Becasue of this, driver is assuming that this is not wildcard scan and so
4409 * is not aging out the scan results.
4410 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07004411 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07004412 {
4413 request->n_ssids = 0;
4414 }
4415
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004416 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07004417 {
4418 tCsrSSIDInfo *SsidInfo;
4419 int j;
4420 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
4421 /* Allocate num_ssid tCsrSSIDInfo structure */
4422 SsidInfo = scanRequest.SSIDs.SSIDList =
4423 ( tCsrSSIDInfo *)vos_mem_malloc(
4424 request->n_ssids*sizeof(tCsrSSIDInfo));
4425
4426 if(NULL == scanRequest.SSIDs.SSIDList)
4427 {
4428 hddLog(VOS_TRACE_LEVEL_ERROR,
4429 "memory alloc failed SSIDInfo buffer");
4430 return -ENOMEM;
4431 }
4432
4433 /* copy all the ssid's and their length */
4434 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
4435 {
4436 /* get the ssid length */
4437 SsidInfo->SSID.length = request->ssids[j].ssid_len;
4438 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
4439 SsidInfo->SSID.length);
4440 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
4441 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
4442 j, SsidInfo->SSID.ssId);
4443 }
4444 /* set the scan type to active */
4445 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4446 }
4447 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4448 {
4449 /* set the scan type to active */
4450 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4451 }
4452 else
4453 {
4454 /*Set the scan type to default type, in this case it is ACTIVE*/
4455 scanRequest.scanType = pScanInfo->scan_mode;
4456 }
4457 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
4458 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4459 }
4460 else
4461 {
4462 /* set the scan type to active */
4463 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4464 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4465
4466 /* set min and max channel time to zero */
4467 scanRequest.minChnTime = 0;
4468 scanRequest.maxChnTime = 0;
4469 }
4470
4471 /* set BSSType to default type */
4472 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4473
4474 /*TODO: scan the requested channels only*/
4475
4476 /*Right now scanning all the channels */
4477 if( request )
4478 {
4479 if( request->n_channels )
4480 {
4481 channelList = vos_mem_malloc( request->n_channels );
4482 if( NULL == channelList )
4483 {
4484 status = -ENOMEM;
4485 goto free_mem;
4486 }
4487
4488 for( i = 0 ; i < request->n_channels ; i++ )
4489 channelList[i] = request->channels[i]->hw_value;
4490 }
4491
4492 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4493 scanRequest.ChannelInfo.ChannelList = channelList;
4494
4495 /* set requestType to full scan */
4496 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004497
4498 /* Flush the scan results(only p2p beacons) for STA scan and P2P
4499 * search (Flush on both full scan and social scan but not on single
4500 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
4501 */
4502
4503 /* Supplicant does single channel scan after 8-way handshake
4504 * and in that case driver shoudnt flush scan results. If
4505 * driver flushes the scan results here and unfortunately if
4506 * the AP doesnt respond to our probe req then association
4507 * fails which is not desired
4508 */
4509
4510 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4511 {
4512 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4513 pAdapter->sessionId );
4514 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004515
4516 if( request->ie_len )
4517 {
4518 /* save this for future association (join requires this) */
4519 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4520 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4521 pScanInfo->scanAddIE.length = request->ie_len;
4522
4523 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004524 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4525 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004526 )
4527 {
4528 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4529 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4530 }
4531
4532 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4533 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4534
Jeff Johnson295189b2012-06-20 16:38:30 -07004535 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4536 request->ie_len);
4537 if (pP2pIe != NULL)
4538 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004539#ifdef WLAN_FEATURE_P2P_DEBUG
4540 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4541 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4542 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4543 {
4544 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4545 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4546 "Go nego completed to Connection is started");
4547 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4548 "for 8way Handshake");
4549 }
4550 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4551 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4552 {
4553 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4554 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4555 "Disconnected state to Connection is started");
4556 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4557 "for 4way Handshake");
4558 }
4559#endif
4560
Jeff Johnsone7245742012-09-05 17:12:55 -07004561 /* no_cck will be set during p2p find to disable 11b rates */
4562 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004563 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004564 hddLog(VOS_TRACE_LEVEL_INFO,
4565 "%s: This is a P2P Search", __func__);
4566 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004567
Jeff Johnsone7245742012-09-05 17:12:55 -07004568 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4569 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004570 /* set requestType to P2P Discovery */
4571 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004572 }
4573
4574 /*
4575 Skip Dfs Channel in case of P2P Search
4576 if it is set in ini file
4577 */
4578 if(cfg_param->skipDfsChnlInP2pSearch)
4579 {
4580 scanRequest.skipDfsChnlInP2pSearch = 1;
4581 }
4582 else
4583 {
4584 scanRequest.skipDfsChnlInP2pSearch = 0;
4585 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004586
Jeff Johnson295189b2012-06-20 16:38:30 -07004587 }
4588 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004589 }
4590 }
4591
4592 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4593
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004594 /* acquire the wakelock to avoid the apps suspend during the scan. To
4595 * address the following issues.
4596 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4597 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4598 * for long time, this result in apps running at full power for long time.
4599 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4600 * be stuck in full power because of resume BMPS
4601 */
4602 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004603
4604 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004605 pAdapter->sessionId, &scanRequest, &scanId,
4606 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004607
Jeff Johnson295189b2012-06-20 16:38:30 -07004608 if (eHAL_STATUS_SUCCESS != status)
4609 {
4610 hddLog(VOS_TRACE_LEVEL_ERROR,
4611 "%s: sme_ScanRequest returned error %d", __func__, status);
4612 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004613 if(eHAL_STATUS_RESOURCES == status)
4614 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004615 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 -07004616 status = -EBUSY;
4617 } else {
4618 status = -EIO;
4619 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004620 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004621 goto free_mem;
4622 }
4623
4624 pScanInfo->mScanPending = TRUE;
4625 pAdapter->request = request;
4626 pScanInfo->scanId = scanId;
4627
4628 complete(&pScanInfo->scan_req_completion_event);
4629
4630free_mem:
4631 if( scanRequest.SSIDs.SSIDList )
4632 {
4633 vos_mem_free(scanRequest.SSIDs.SSIDList);
4634 }
4635
4636 if( channelList )
4637 vos_mem_free( channelList );
4638
4639 EXIT();
4640
4641 return status;
4642}
4643
4644/*
4645 * FUNCTION: wlan_hdd_cfg80211_connect_start
4646 * This function is used to start the association process
4647 */
4648int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004649 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004650{
4651 int status = 0;
4652 hdd_wext_state_t *pWextState;
4653 v_U32_t roamId;
4654 tCsrRoamProfile *pRoamProfile;
4655 eMib_dot11DesiredBssType connectedBssType;
4656 eCsrAuthType RSNAuthType;
4657
4658 ENTER();
4659
4660 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4661
4662 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4663 {
4664 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4665 return -EINVAL;
4666 }
4667
4668 pRoamProfile = &pWextState->roamProfile;
4669
4670 if (pRoamProfile)
4671 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004672 int ret = 0;
4673 hdd_station_ctx_t *pHddStaCtx;
4674 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4675 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4676
4677 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4678 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4679 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004680 {
4681 /* Issue disconnect to CSR */
4682 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4683 if( eHAL_STATUS_SUCCESS ==
4684 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4685 pAdapter->sessionId,
4686 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4687 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004688 ret = wait_for_completion_interruptible_timeout(
4689 &pAdapter->disconnect_comp_var,
4690 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4691 if (0 == ret)
4692 {
4693 VOS_ASSERT(0);
4694 }
4695 }
4696 }
4697 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4698 {
4699 ret = wait_for_completion_interruptible_timeout(
4700 &pAdapter->disconnect_comp_var,
4701 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4702 if (0 == ret)
4703 {
4704 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004705 }
4706 }
4707
4708 if (HDD_WMM_USER_MODE_NO_QOS ==
4709 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4710 {
4711 /*QoS not enabled in cfg file*/
4712 pRoamProfile->uapsd_mask = 0;
4713 }
4714 else
4715 {
4716 /*QoS enabled, update uapsd mask from cfg file*/
4717 pRoamProfile->uapsd_mask =
4718 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4719 }
4720
4721 pRoamProfile->SSIDs.numOfSSIDs = 1;
4722 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4723 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
4724 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
4725 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4726 ssid, ssid_len);
4727
4728 if (bssid)
4729 {
4730 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4731 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4732 WNI_CFG_BSSID_LEN);
4733 /* Save BSSID in seperate variable as well, as RoamProfile
4734 BSSID is getting zeroed out in the association process. And in
4735 case of join failure we should send valid BSSID to supplicant
4736 */
4737 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4738 WNI_CFG_BSSID_LEN);
4739 }
4740
4741 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4742 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4743 {
4744 /*set gen ie*/
4745 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4746 /*set auth*/
4747 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4748 }
4749 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4750 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4751 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4752 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4753 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4754 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4755 )
4756 {
4757 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4758 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4759 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4760 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4761 eCSR_AUTH_TYPE_AUTOSWITCH;
4762 pWextState->roamProfile.AuthType.authType[0] =
4763 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4764 }
4765#ifdef FEATURE_WLAN_WAPI
4766 if (pAdapter->wapi_info.nWapiMode)
4767 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004768 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004769 switch (pAdapter->wapi_info.wapiAuthMode)
4770 {
4771 case WAPI_AUTH_MODE_PSK:
4772 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004773 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004774 pAdapter->wapi_info.wapiAuthMode);
4775 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4776 break;
4777 }
4778 case WAPI_AUTH_MODE_CERT:
4779 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004780 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004781 pAdapter->wapi_info.wapiAuthMode);
4782 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4783 break;
4784 }
4785 } // End of switch
4786 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4787 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4788 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004789 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004790 pRoamProfile->AuthType.numEntries = 1;
4791 pRoamProfile->EncryptionType.numEntries = 1;
4792 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4793 pRoamProfile->mcEncryptionType.numEntries = 1;
4794 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4795 }
4796 }
4797#endif /* FEATURE_WLAN_WAPI */
4798 pRoamProfile->csrPersona = pAdapter->device_mode;
4799
Jeff Johnson32d95a32012-09-10 13:15:23 -07004800 if( operatingChannel )
4801 {
4802 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4803 pRoamProfile->ChannelInfo.numOfChannels = 1;
4804 }
4805
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004806 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
4807 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
4808 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
4809 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004810 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
4811 */
4812 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4813 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
4814 eConnectionState_Connecting);
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004815
Jeff Johnson295189b2012-06-20 16:38:30 -07004816 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4817 pAdapter->sessionId, pRoamProfile, &roamId);
4818
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004819 if( (eHAL_STATUS_SUCCESS != status) &&
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304820 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
4821
4822 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004823 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
4824 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
4825 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304826 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004827 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304828 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004829
4830 pRoamProfile->ChannelInfo.ChannelList = NULL;
4831 pRoamProfile->ChannelInfo.numOfChannels = 0;
4832
Jeff Johnson295189b2012-06-20 16:38:30 -07004833 }
4834 else
4835 {
4836 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4837 return -EINVAL;
4838 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004839 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004840 return status;
4841}
4842
4843/*
4844 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4845 * This function is used to set the authentication type (OPEN/SHARED).
4846 *
4847 */
4848static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4849 enum nl80211_auth_type auth_type)
4850{
4851 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4852 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4853
4854 ENTER();
4855
4856 /*set authentication type*/
4857 switch (auth_type)
4858 {
4859 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4860 case NL80211_AUTHTYPE_AUTOMATIC:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07004861#ifdef WLAN_FEATURE_VOWIFI_11R
4862 case NL80211_AUTHTYPE_FT:
4863#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07004864 hddLog(VOS_TRACE_LEVEL_INFO,
4865 "%s: set authentication type to OPEN", __func__);
4866 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4867 break;
4868
4869 case NL80211_AUTHTYPE_SHARED_KEY:
4870 hddLog(VOS_TRACE_LEVEL_INFO,
4871 "%s: set authentication type to SHARED", __func__);
4872 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4873 break;
4874#ifdef FEATURE_WLAN_CCX
4875 case NL80211_AUTHTYPE_NETWORK_EAP:
4876 hddLog(VOS_TRACE_LEVEL_INFO,
4877 "%s: set authentication type to CCKM WPA", __func__);
4878 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4879 break;
4880#endif
4881
4882
4883 default:
4884 hddLog(VOS_TRACE_LEVEL_ERROR,
4885 "%s: Unsupported authentication type %d", __func__,
4886 auth_type);
4887 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4888 return -EINVAL;
4889 }
4890
4891 pWextState->roamProfile.AuthType.authType[0] =
4892 pHddStaCtx->conn_info.authType;
4893 return 0;
4894}
4895
4896/*
4897 * FUNCTION: wlan_hdd_set_akm_suite
4898 * This function is used to set the key mgmt type(PSK/8021x).
4899 *
4900 */
4901static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
4902 u32 key_mgmt
4903 )
4904{
4905 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4906 ENTER();
4907
4908 /*set key mgmt type*/
4909 switch(key_mgmt)
4910 {
4911 case WLAN_AKM_SUITE_PSK:
4912 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
4913 __func__);
4914 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
4915 break;
4916
4917 case WLAN_AKM_SUITE_8021X:
4918 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
4919 __func__);
4920 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
4921 break;
4922#ifdef FEATURE_WLAN_CCX
4923#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
4924#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
4925 case WLAN_AKM_SUITE_CCKM:
4926 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
4927 __func__);
4928 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
4929 break;
4930#endif
4931
4932 default:
4933 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
4934 __func__, key_mgmt);
4935 return -EINVAL;
4936
4937 }
4938 return 0;
4939}
4940
4941/*
4942 * FUNCTION: wlan_hdd_cfg80211_set_cipher
4943 * This function is used to set the encryption type
4944 * (NONE/WEP40/WEP104/TKIP/CCMP).
4945 */
4946static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
4947 u32 cipher,
4948 bool ucast
4949 )
4950{
4951 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4952 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4953 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4954
4955 ENTER();
4956
4957 if (!cipher)
4958 {
4959 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
4960 __func__, cipher);
4961 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4962 }
4963 else
4964 {
4965
4966 /*set encryption method*/
4967 switch (cipher)
4968 {
4969 case IW_AUTH_CIPHER_NONE:
4970 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4971 break;
4972
4973 case WLAN_CIPHER_SUITE_WEP40:
4974 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4975 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4976 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
4977 else
4978 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4979 break;
4980
4981 case WLAN_CIPHER_SUITE_WEP104:
4982 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4983 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4984 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
4985 else
4986 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
4987 break;
4988
4989 case WLAN_CIPHER_SUITE_TKIP:
4990 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
4991 break;
4992
4993 case WLAN_CIPHER_SUITE_CCMP:
4994 encryptionType = eCSR_ENCRYPT_TYPE_AES;
4995 break;
4996#ifdef FEATURE_WLAN_WAPI
4997 case WLAN_CIPHER_SUITE_SMS4:
4998 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
4999 break;
5000#endif
5001
5002#ifdef FEATURE_WLAN_CCX
5003 case WLAN_CIPHER_SUITE_KRK:
5004 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
5005 break;
5006#endif
5007 default:
5008 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
5009 __func__, cipher);
5010 return -EOPNOTSUPP;
5011 }
5012 }
5013
5014 if (ucast)
5015 {
5016 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
5017 __func__, encryptionType);
5018 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5019 pWextState->roamProfile.EncryptionType.numEntries = 1;
5020 pWextState->roamProfile.EncryptionType.encryptionType[0] =
5021 encryptionType;
5022 }
5023 else
5024 {
5025 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
5026 __func__, encryptionType);
5027 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
5028 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
5029 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
5030 }
5031
5032 return 0;
5033}
5034
5035
5036/*
5037 * FUNCTION: wlan_hdd_cfg80211_set_ie
5038 * This function is used to parse WPA/RSN IE's.
5039 */
5040int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
5041 u8 *ie,
5042 size_t ie_len
5043 )
5044{
5045 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5046 u8 *genie = ie;
5047 v_U16_t remLen = ie_len;
5048#ifdef FEATURE_WLAN_WAPI
5049 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
5050 u16 *tmp;
5051 v_U16_t akmsuiteCount;
5052 int *akmlist;
5053#endif
5054 ENTER();
5055
5056 /* clear previous assocAddIE */
5057 pWextState->assocAddIE.length = 0;
5058 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
5059
5060 while (remLen >= 2)
5061 {
5062 v_U16_t eLen = 0;
5063 v_U8_t elementId;
5064 elementId = *genie++;
5065 eLen = *genie++;
5066 remLen -= 2;
5067
5068 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
5069 __func__, elementId, eLen);
5070
5071 switch ( elementId )
5072 {
5073 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005074 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 -07005075 {
5076 hddLog(VOS_TRACE_LEVEL_ERROR,
5077 "%s: Invalid WPA IE", __func__);
5078 return -EINVAL;
5079 }
5080 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
5081 {
5082 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5083 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
5084 __func__, eLen + 2);
5085
5086 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5087 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005088 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
5089 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005090 VOS_ASSERT(0);
5091 return -ENOMEM;
5092 }
5093 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5094 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5095 pWextState->assocAddIE.length += eLen + 2;
5096
5097 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
5098 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5099 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5100 }
5101 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
5102 {
5103 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
5104 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5105 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
5106 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
5107 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
5108 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005109 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
5110 P2P_OUI_TYPE_SIZE))
5111 /*Consider P2P IE, only for P2P Client */
5112 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5113 {
5114 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5115 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
5116 __func__, eLen + 2);
5117
5118 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5119 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005120 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5121 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005122 VOS_ASSERT(0);
5123 return -ENOMEM;
5124 }
5125 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5126 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5127 pWextState->assocAddIE.length += eLen + 2;
5128
5129 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5130 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5131 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005132#ifdef WLAN_FEATURE_WFD
5133 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
5134 WFD_OUI_TYPE_SIZE))
5135 /*Consider WFD IE, only for P2P Client */
5136 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5137 {
5138 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5139 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
5140 __func__, eLen + 2);
5141
5142 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5143 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005144 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5145 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005146 VOS_ASSERT(0);
5147 return -ENOMEM;
5148 }
5149 // WFD IE is saved to Additional IE ; it should be accumulated to handle
5150 // WPS IE + P2P IE + WFD IE
5151 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5152 pWextState->assocAddIE.length += eLen + 2;
5153
5154 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5155 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5156 }
5157#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005158 /* Appending HS 2.0 Indication Element in Assiciation Request */
5159 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005160 HS20_OUI_TYPE_SIZE)) )
5161 {
5162 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5163 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
5164 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005165
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005166 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5167 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005168 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5169 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005170 VOS_ASSERT(0);
5171 return -ENOMEM;
5172 }
5173 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5174 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005175
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005176 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5177 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5178 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005179
Jeff Johnson295189b2012-06-20 16:38:30 -07005180 break;
5181 case DOT11F_EID_RSN:
5182 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
5183 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5184 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
5185 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
5186 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
5187 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005188 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
5189 case DOT11F_EID_EXTCAP:
5190 {
5191 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5192 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
5193 __func__, eLen + 2);
5194
5195 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5196 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005197 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5198 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005199 VOS_ASSERT(0);
5200 return -ENOMEM;
5201 }
5202 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5203 pWextState->assocAddIE.length += eLen + 2;
5204
5205 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5206 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5207 break;
5208 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005209#ifdef FEATURE_WLAN_WAPI
5210 case WLAN_EID_WAPI:
5211 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
5212 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
5213 pAdapter->wapi_info.nWapiMode);
5214 tmp = (u16 *)ie;
5215 tmp = tmp + 2; // Skip element Id and Len, Version
5216 akmsuiteCount = WPA_GET_LE16(tmp);
5217 tmp = tmp + 1;
5218 akmlist = (int *)(tmp);
5219 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
5220 {
5221 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
5222 }
5223 else
5224 {
5225 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
5226 VOS_ASSERT(0);
5227 return -EINVAL;
5228 }
5229
5230 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
5231 {
5232 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005233 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005234 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
5235 }
5236 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
5237 {
5238 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005239 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005240 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
5241 }
5242 break;
5243#endif
5244 default:
5245 hddLog (VOS_TRACE_LEVEL_ERROR,
5246 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005247 /* when Unknown IE is received we should break and continue
5248 * to the next IE in the buffer instead we were returning
5249 * so changing this to break */
5250 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005251 }
5252 genie += eLen;
5253 remLen -= eLen;
5254 }
5255 EXIT();
5256 return 0;
5257}
5258
5259/*
5260 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5261 * This function is used to initialize the security
5262 * parameters during connect operation.
5263 */
5264int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
5265 struct cfg80211_connect_params *req
5266 )
5267{
5268 int status = 0;
5269 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5270 ENTER();
5271
5272 /*set wpa version*/
5273 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5274
5275 if (req->crypto.wpa_versions)
5276 {
5277 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
5278 && ( (req->ie_len)
5279 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
5280 // Make sure that it is including a WPA IE.
5281 /* Currently NL is putting WPA version 1 even for open,
5282 * since p2p ie is also put in same buffer.
5283 * */
5284 {
5285 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5286 }
5287 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
5288 {
5289 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5290 }
5291 }
5292
5293 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
5294 pWextState->wpaVersion);
5295
5296 /*set authentication type*/
5297 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
5298
5299 if (0 > status)
5300 {
5301 hddLog(VOS_TRACE_LEVEL_ERROR,
5302 "%s: failed to set authentication type ", __func__);
5303 return status;
5304 }
5305
5306 /*set key mgmt type*/
5307 if (req->crypto.n_akm_suites)
5308 {
5309 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
5310 if (0 > status)
5311 {
5312 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
5313 __func__);
5314 return status;
5315 }
5316 }
5317
5318 /*set pairwise cipher type*/
5319 if (req->crypto.n_ciphers_pairwise)
5320 {
5321 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
5322 req->crypto.ciphers_pairwise[0], true);
5323 if (0 > status)
5324 {
5325 hddLog(VOS_TRACE_LEVEL_ERROR,
5326 "%s: failed to set unicast cipher type", __func__);
5327 return status;
5328 }
5329 }
5330 else
5331 {
5332 /*Reset previous cipher suite to none*/
5333 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
5334 if (0 > status)
5335 {
5336 hddLog(VOS_TRACE_LEVEL_ERROR,
5337 "%s: failed to set unicast cipher type", __func__);
5338 return status;
5339 }
5340 }
5341
5342 /*set group cipher type*/
5343 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
5344 false);
5345
5346 if (0 > status)
5347 {
5348 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
5349 __func__);
5350 return status;
5351 }
5352
5353 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
5354 if (req->ie_len)
5355 {
5356 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
5357 if ( 0 > status)
5358 {
5359 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
5360 __func__);
5361 return status;
5362 }
5363 }
5364
5365 /*incase of WEP set default key information*/
5366 if (req->key && req->key_len)
5367 {
5368 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
5369 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
5370 )
5371 {
5372 if ( IW_AUTH_KEY_MGMT_802_1X
5373 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
5374 {
5375 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
5376 __func__);
5377 return -EOPNOTSUPP;
5378 }
5379 else
5380 {
5381 u8 key_len = req->key_len;
5382 u8 key_idx = req->key_idx;
5383
5384 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
5385 && (CSR_MAX_NUM_KEY > key_idx)
5386 )
5387 {
5388 hddLog(VOS_TRACE_LEVEL_INFO,
5389 "%s: setting default wep key, key_idx = %hu key_len %hu",
5390 __func__, key_idx, key_len);
5391 vos_mem_copy(
5392 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
5393 req->key, key_len);
5394 pWextState->roamProfile.Keys.KeyLength[key_idx] =
5395 (u8)key_len;
5396 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
5397 }
5398 }
5399 }
5400 }
5401
5402 return status;
5403}
5404
5405/*
5406 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5407 * This function is used to initialize the security
5408 * parameters during connect operation.
5409 */
5410static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
5411 struct net_device *ndev,
5412 struct cfg80211_connect_params *req
5413 )
5414{
5415 int status = 0;
5416 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
5417 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
5418 hdd_context_t *pHddCtx = NULL;
5419
5420 ENTER();
5421
5422 hddLog(VOS_TRACE_LEVEL_INFO,
5423 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5424
5425 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5426 {
5427 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5428 "%s:LOGP in Progress. Ignore!!!", __func__);
5429 return -EAGAIN;
5430 }
5431
5432#ifdef WLAN_BTAMP_FEATURE
5433 //Infra connect not supported when AMP traffic is on.
5434 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
5435 {
5436 hddLog(VOS_TRACE_LEVEL_ERROR,
5437 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005438 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07005439 }
5440#endif
5441 /*initialise security parameters*/
5442 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
5443
5444 if ( 0 > status)
5445 {
5446 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
5447 __func__);
5448 return status;
5449 }
5450
5451 //If Device Mode is Station Concurrent Sessions Exit BMps
Jeff Johnsona8a1a482012-12-12 16:49:33 -08005452 //P2P Mode will be taken care in Open/close adapter
Jeff Johnson295189b2012-06-20 16:38:30 -07005453 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
5454 (vos_concurrent_sessions_running()))
5455 {
5456 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5457
5458 if (NULL != pVosContext)
5459 {
5460 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5461 if(NULL != pHddCtx)
5462 {
5463 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
5464 }
5465 }
5466 }
5467
Mohit Khanna765234a2012-09-11 15:08:35 -07005468 if ( req->channel )
5469 {
5470 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5471 req->ssid_len, req->bssid,
5472 req->channel->hw_value);
5473 }
5474 else
5475 {
5476 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5477 req->ssid_len, req->bssid,
5478 0);
5479 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005480
5481 if (0 > status)
5482 {
5483 //ReEnable BMPS if disabled
5484 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5485 (NULL != pHddCtx))
5486 {
5487 //ReEnable Bmps and Imps back
5488 hdd_enable_bmps_imps(pHddCtx);
5489 }
5490
5491 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5492 return status;
5493 }
5494 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
5495 EXIT();
5496 return status;
5497}
5498
5499
5500/*
5501 * FUNCTION: wlan_hdd_cfg80211_disconnect
5502 * This function is used to issue a disconnect request to SME
5503 */
5504static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
5505 struct net_device *dev,
5506 u16 reason
5507 )
5508{
5509 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5510 tCsrRoamProfile *pRoamProfile =
5511 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
5512 int status = 0;
5513 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005514#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005515 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005516 tANI_U8 staIdx;
5517#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005518
5519 ENTER();
5520
5521 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
5522 __func__,pAdapter->device_mode);
5523
5524 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5525 __func__, reason);
5526
5527 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
5528 {
5529 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5530 "%s:LOGP in Progress. Ignore!!!",__func__);
5531 return -EAGAIN;
5532 }
5533 if (NULL != pRoamProfile)
5534 {
5535 /*issue disconnect request to SME, if station is in connected state*/
5536 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
5537 {
5538 eCsrRoamDisconnectReason reasonCode =
5539 eCSR_DISCONNECT_REASON_UNSPECIFIED;
5540 switch(reason)
5541 {
5542 case WLAN_REASON_MIC_FAILURE:
5543 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
5544 break;
5545
5546 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
5547 case WLAN_REASON_DISASSOC_AP_BUSY:
5548 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
5549 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
5550 break;
5551
5552 case WLAN_REASON_PREV_AUTH_NOT_VALID:
5553 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
5554 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
5555 break;
5556
5557 case WLAN_REASON_DEAUTH_LEAVING:
5558 default:
5559 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
5560 break;
5561 }
5562 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5563 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
5564 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5565
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005566#ifdef FEATURE_WLAN_TDLS
5567 /* First clean up the tdls peers if any */
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005568 for (staIdx = 0 ; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005569 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005570 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId == pAdapter->sessionId) &&
5571 (pHddCtx->tdlsConnInfo[staIdx].staId))
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005572 {
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005573 uint8 *mac;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005574 mac = pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005575 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07005576 "%s: call sme_DeleteTdlsPeerSta staId %d sessionId %d " MAC_ADDRESS_STR,
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005577 __func__, pHddCtx->tdlsConnInfo[staIdx].staId, pAdapter->sessionId,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07005578 MAC_ADDR_ARRAY(mac));
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005579 sme_DeleteTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005580 pAdapter->sessionId,
5581 mac);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005582 }
5583 }
5584#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005585 /*issue disconnect*/
5586 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5587 pAdapter->sessionId, reasonCode);
5588
5589 if ( 0 != status)
5590 {
5591 hddLog(VOS_TRACE_LEVEL_ERROR,
5592 "%s csrRoamDisconnect failure, returned %d \n",
5593 __func__, (int)status );
5594 return -EINVAL;
5595 }
5596
5597 wait_for_completion_interruptible_timeout(
5598 &pAdapter->disconnect_comp_var,
5599 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5600
5601
5602 /*stop tx queues*/
5603 netif_tx_disable(dev);
5604 netif_carrier_off(dev);
5605 }
5606 }
5607 else
5608 {
5609 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
5610 }
5611
5612 return status;
5613}
5614
5615/*
5616 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
5617 * This function is used to initialize the security
5618 * settings in IBSS mode.
5619 */
5620static int wlan_hdd_cfg80211_set_privacy_ibss(
5621 hdd_adapter_t *pAdapter,
5622 struct cfg80211_ibss_params *params
5623 )
5624{
5625 int status = 0;
5626 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5627 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5628 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5629
5630 ENTER();
5631
5632 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5633
5634 if (params->ie_len && ( NULL != params->ie) )
5635 {
5636 if (WLAN_EID_RSN == params->ie[0])
5637 {
5638 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5639 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5640 }
5641 else
5642 {
5643 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5644 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5645 }
5646 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
5647
5648 if (0 > status)
5649 {
5650 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
5651 __func__);
5652 return status;
5653 }
5654 }
5655
5656 pWextState->roamProfile.AuthType.authType[0] =
5657 pHddStaCtx->conn_info.authType =
5658 eCSR_AUTH_TYPE_OPEN_SYSTEM;
5659
5660 if (params->privacy)
5661 {
5662 /* Security enabled IBSS, At this time there is no information available
5663 * about the security paramters, so initialise the encryption type to
5664 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
5665 * The correct security parameters will be updated later in
5666 * wlan_hdd_cfg80211_add_key */
5667 /* Hal expects encryption type to be set inorder
5668 *enable privacy bit in beacons */
5669
5670 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5671 }
5672
5673 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5674 pWextState->roamProfile.EncryptionType.numEntries = 1;
5675 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
5676
5677 return status;
5678}
5679
5680/*
5681 * FUNCTION: wlan_hdd_cfg80211_join_ibss
5682 * This function is used to create/join an IBSS
5683 */
5684static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
5685 struct net_device *dev,
5686 struct cfg80211_ibss_params *params
5687 )
5688{
5689 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5690 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5691 tCsrRoamProfile *pRoamProfile;
5692 int status;
5693 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5694
5695 ENTER();
5696
5697 hddLog(VOS_TRACE_LEVEL_INFO,
5698 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5699
5700 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5701 {
5702 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5703 "%s:LOGP in Progress. Ignore!!!", __func__);
5704 return -EAGAIN;
5705 }
5706
5707 if (NULL == pWextState)
5708 {
5709 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5710 __func__);
5711 return -EIO;
5712 }
5713
5714 pRoamProfile = &pWextState->roamProfile;
5715
5716 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
5717 {
5718 hddLog (VOS_TRACE_LEVEL_ERROR,
5719 "%s Interface type is not set to IBSS \n", __func__);
5720 return -EINVAL;
5721 }
5722
5723 /* Set Channel */
5724 if (NULL != params->channel)
5725 {
5726 u8 channelNum;
5727 if (IEEE80211_BAND_5GHZ == params->channel->band)
5728 {
5729 hddLog(VOS_TRACE_LEVEL_ERROR,
5730 "%s: IBSS join is called with unsupported band %d",
5731 __func__, params->channel->band);
5732 return -EOPNOTSUPP;
5733 }
5734
5735 /* Get channel number */
5736 channelNum =
5737 ieee80211_frequency_to_channel(params->channel->center_freq);
5738
5739 /*TODO: use macro*/
5740 if (14 >= channelNum)
5741 {
5742 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5743 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5744 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5745 int indx;
5746
5747 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5748 validChan, &numChans))
5749 {
5750 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
5751 __func__);
5752 return -EOPNOTSUPP;
5753 }
5754
5755 for (indx = 0; indx < numChans; indx++)
5756 {
5757 if (channelNum == validChan[indx])
5758 {
5759 break;
5760 }
5761 }
5762 if (indx >= numChans)
5763 {
5764 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
5765 __func__, channelNum);
5766 return -EINVAL;
5767 }
5768 /* Set the Operational Channel */
5769 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
5770 channelNum);
5771 pRoamProfile->ChannelInfo.numOfChannels = 1;
5772 pHddStaCtx->conn_info.operationChannel = channelNum;
5773 pRoamProfile->ChannelInfo.ChannelList =
5774 &pHddStaCtx->conn_info.operationChannel;
5775 }
5776 else
5777 {
5778 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5779 __func__, channelNum);
5780 return -EINVAL;
5781 }
5782 }
5783
5784 /* Initialize security parameters */
5785 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5786 if (status < 0)
5787 {
5788 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5789 __func__);
5790 return status;
5791 }
5792
5793 /* Issue connect start */
5794 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005795 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005796
5797 if (0 > status)
5798 {
5799 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5800 return status;
5801 }
5802
5803 return 0;
5804}
5805
5806/*
5807 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5808 * This function is used to leave an IBSS
5809 */
5810static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5811 struct net_device *dev
5812 )
5813{
5814 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5815 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5816 tCsrRoamProfile *pRoamProfile;
5817
5818 ENTER();
5819
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005820 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5821 {
5822 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5823 "%s:LOGP in Progress. Ignore!!!", __func__);
5824 return -EAGAIN;
5825 }
5826
Jeff Johnson295189b2012-06-20 16:38:30 -07005827 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5828 if (NULL == pWextState)
5829 {
5830 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5831 __func__);
5832 return -EIO;
5833 }
5834
5835 pRoamProfile = &pWextState->roamProfile;
5836
5837 /* Issue disconnect only if interface type is set to IBSS */
5838 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5839 {
5840 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5841 __func__);
5842 return -EINVAL;
5843 }
5844
5845 /* Issue Disconnect request */
5846 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5847 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5848 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5849
5850 return 0;
5851}
5852
5853/*
5854 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5855 * This function is used to set the phy parameters
5856 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5857 */
5858static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5859 u32 changed)
5860{
5861 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5862 tHalHandle hHal = pHddCtx->hHal;
5863
5864 ENTER();
5865
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005866 if ( pHddCtx->isLogpInProgress )
5867 {
5868 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5869 "%s:LOGP in Progress. Ignore!!!", __func__);
5870 return -EAGAIN;
5871 }
5872
Jeff Johnson295189b2012-06-20 16:38:30 -07005873 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
5874 {
5875 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
5876 WNI_CFG_RTS_THRESHOLD_STAMAX :
5877 wiphy->rts_threshold;
5878
5879 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
5880 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
5881 {
5882 hddLog(VOS_TRACE_LEVEL_ERROR,
5883 "%s: Invalid RTS Threshold value %hu",
5884 __func__, rts_threshold);
5885 return -EINVAL;
5886 }
5887
5888 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
5889 rts_threshold, ccmCfgSetCallback,
5890 eANI_BOOLEAN_TRUE))
5891 {
5892 hddLog(VOS_TRACE_LEVEL_ERROR,
5893 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
5894 __func__, rts_threshold);
5895 return -EIO;
5896 }
5897
5898 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
5899 rts_threshold);
5900 }
5901
5902 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
5903 {
5904 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
5905 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
5906 wiphy->frag_threshold;
5907
5908 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
5909 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
5910 {
5911 hddLog(VOS_TRACE_LEVEL_ERROR,
5912 "%s: Invalid frag_threshold value %hu", __func__,
5913 frag_threshold);
5914 return -EINVAL;
5915 }
5916
5917 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
5918 frag_threshold, ccmCfgSetCallback,
5919 eANI_BOOLEAN_TRUE))
5920 {
5921 hddLog(VOS_TRACE_LEVEL_ERROR,
5922 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
5923 __func__, frag_threshold);
5924 return -EIO;
5925 }
5926
5927 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
5928 frag_threshold);
5929 }
5930
5931 if ((changed & WIPHY_PARAM_RETRY_SHORT)
5932 || (changed & WIPHY_PARAM_RETRY_LONG))
5933 {
5934 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
5935 wiphy->retry_short :
5936 wiphy->retry_long;
5937
5938 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
5939 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
5940 {
5941 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
5942 __func__, retry_value);
5943 return -EINVAL;
5944 }
5945
5946 if (changed & WIPHY_PARAM_RETRY_SHORT)
5947 {
5948 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
5949 retry_value, ccmCfgSetCallback,
5950 eANI_BOOLEAN_TRUE))
5951 {
5952 hddLog(VOS_TRACE_LEVEL_ERROR,
5953 "%s: ccmCfgSetInt failed for long retry count %hu",
5954 __func__, retry_value);
5955 return -EIO;
5956 }
5957 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
5958 __func__, retry_value);
5959 }
5960 else if (changed & WIPHY_PARAM_RETRY_SHORT)
5961 {
5962 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
5963 retry_value, ccmCfgSetCallback,
5964 eANI_BOOLEAN_TRUE))
5965 {
5966 hddLog(VOS_TRACE_LEVEL_ERROR,
5967 "%s: ccmCfgSetInt failed for short retry count %hu",
5968 __func__, retry_value);
5969 return -EIO;
5970 }
5971 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
5972 __func__, retry_value);
5973 }
5974 }
5975
5976 return 0;
5977}
5978
5979/*
5980 * FUNCTION: wlan_hdd_cfg80211_set_txpower
5981 * This function is used to set the txpower
5982 */
5983static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
5984#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
5985 enum tx_power_setting type,
5986#else
5987 enum nl80211_tx_power_setting type,
5988#endif
5989 int dbm)
5990{
5991 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5992 tHalHandle hHal = pHddCtx->hHal;
5993 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5994 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5995
5996 ENTER();
5997
5998 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
5999 dbm, ccmCfgSetCallback,
6000 eANI_BOOLEAN_TRUE))
6001 {
6002 hddLog(VOS_TRACE_LEVEL_ERROR,
6003 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
6004 return -EIO;
6005 }
6006
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006007 if ( pHddCtx->isLogpInProgress )
6008 {
6009 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6010 "%s:LOGP in Progress. Ignore!!!", __func__);
6011 return -EAGAIN;
6012 }
6013
Jeff Johnson295189b2012-06-20 16:38:30 -07006014 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
6015 dbm);
6016
6017 switch(type)
6018 {
6019 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
6020 /* Fall through */
6021 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
6022 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
6023 {
6024 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
6025 __func__);
6026 return -EIO;
6027 }
6028 break;
6029 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
6030 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
6031 __func__);
6032 return -EOPNOTSUPP;
6033 break;
6034 default:
6035 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
6036 __func__, type);
6037 return -EIO;
6038 }
6039
6040 return 0;
6041}
6042
6043/*
6044 * FUNCTION: wlan_hdd_cfg80211_get_txpower
6045 * This function is used to read the txpower
6046 */
6047static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
6048{
6049
6050 hdd_adapter_t *pAdapter;
6051 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6052
Jeff Johnsone7245742012-09-05 17:12:55 -07006053 ENTER();
6054
Jeff Johnson295189b2012-06-20 16:38:30 -07006055 if (NULL == pHddCtx)
6056 {
6057 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
6058 *dbm = 0;
6059 return -ENOENT;
6060 }
6061
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006062 if ( pHddCtx->isLogpInProgress )
6063 {
6064 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6065 "%s:LOGP in Progress. Ignore!!!", __func__);
6066 return -EAGAIN;
6067 }
6068
Jeff Johnson295189b2012-06-20 16:38:30 -07006069 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
6070 if (NULL == pAdapter)
6071 {
6072 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
6073 return -ENOENT;
6074 }
6075
6076 wlan_hdd_get_classAstats(pAdapter);
6077 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
6078
Jeff Johnsone7245742012-09-05 17:12:55 -07006079 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006080 return 0;
6081}
6082
6083static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
6084 u8* mac, struct station_info *sinfo)
6085{
6086 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
6087 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6088 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
6089 tANI_U8 rate_flags;
6090
6091 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6092 hdd_config_t *pCfg = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07006093
6094 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
6095 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
6096 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
6097 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
6098 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
6099 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
6100 tANI_U16 maxRate = 0;
6101 tANI_U16 myRate;
6102 tANI_U16 currentRate = 0;
6103 tANI_U8 maxSpeedMCS = 0;
6104 tANI_U8 maxMCSIdx = 0;
6105 tANI_U8 rateFlag = 1;
6106 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006107 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07006108
Jeff Johnsone7245742012-09-05 17:12:55 -07006109 ENTER();
6110
Jeff Johnson295189b2012-06-20 16:38:30 -07006111 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
6112 (0 == ssidlen))
6113 {
6114 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
6115 " Invalid ssidlen, %d", __func__, ssidlen);
6116 /*To keep GUI happy*/
6117 return 0;
6118 }
6119
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006120 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6121 {
6122 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6123 "%s:LOGP in Progress. Ignore!!!", __func__);
6124 return -EAGAIN;
6125 }
6126
Jeff Johnson295189b2012-06-20 16:38:30 -07006127 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
6128 sinfo->filled |= STATION_INFO_SIGNAL;
6129
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006130 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006131 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
6132
6133 //convert to the UI units of 100kbps
6134 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
6135
6136#ifdef LINKSPEED_DEBUG_ENABLED
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006137 pr_info("RSSI %d, RLMS %u, rate %d, rssi high %d, rssi mid %d, rssi low %d, rate_flags 0x%x\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07006138 sinfo->signal,
6139 pCfg->reportMaxLinkSpeed,
6140 myRate,
6141 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006142 (int) pCfg->linkSpeedRssiMid,
6143 (int) pCfg->linkSpeedRssiLow,
6144 (int) rate_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07006145#endif //LINKSPEED_DEBUG_ENABLED
6146
6147 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
6148 {
6149 // we do not want to necessarily report the current speed
6150 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
6151 {
6152 // report the max possible speed
6153 rssidx = 0;
6154 }
6155 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
6156 {
6157 // report the max possible speed with RSSI scaling
6158 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
6159 {
6160 // report the max possible speed
6161 rssidx = 0;
6162 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006163 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07006164 {
6165 // report middle speed
6166 rssidx = 1;
6167 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006168 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
6169 {
6170 // report middle speed
6171 rssidx = 2;
6172 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006173 else
6174 {
6175 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006176 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07006177 }
6178 }
6179 else
6180 {
6181 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
6182 hddLog(VOS_TRACE_LEVEL_ERROR,
6183 "%s: Invalid value for reportMaxLinkSpeed: %u",
6184 __func__, pCfg->reportMaxLinkSpeed);
6185 rssidx = 0;
6186 }
6187
6188 maxRate = 0;
6189
6190 /* Get Basic Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306191 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_OPERATIONAL_RATE_SET,
6192 OperationalRates, &ORLeng))
6193 {
6194 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6195 /*To keep GUI happy*/
6196 return 0;
6197 }
6198
Jeff Johnson295189b2012-06-20 16:38:30 -07006199 for (i = 0; i < ORLeng; i++)
6200 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006201 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006202 {
6203 /* Validate Rate Set */
6204 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
6205 {
6206 currentRate = supported_data_rate[j].supported_rate[rssidx];
6207 break;
6208 }
6209 }
6210 /* Update MAX rate */
6211 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6212 }
6213
6214 /* Get Extended Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306215 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
6216 ExtendedRates, &ERLeng))
6217 {
6218 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6219 /*To keep GUI happy*/
6220 return 0;
6221 }
6222
Jeff Johnson295189b2012-06-20 16:38:30 -07006223 for (i = 0; i < ERLeng; i++)
6224 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006225 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006226 {
6227 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
6228 {
6229 currentRate = supported_data_rate[j].supported_rate[rssidx];
6230 break;
6231 }
6232 }
6233 /* Update MAX rate */
6234 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6235 }
6236
6237 /* Get MCS Rate Set -- but only if we are connected at MCS
6238 rates or if we are always reporting max speed or if we have
6239 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006240 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07006241 {
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306242 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_CURRENT_MCS_SET,
6243 MCSRates, &MCSLeng))
6244 {
6245 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6246 /*To keep GUI happy*/
6247 return 0;
6248 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006249 rateFlag = 0;
6250 if (rate_flags & eHAL_TX_RATE_HT40)
6251 {
6252 rateFlag |= 1;
6253 }
6254 if (rate_flags & eHAL_TX_RATE_SGI)
6255 {
6256 rateFlag |= 2;
6257 }
6258
6259 for (i = 0; i < MCSLeng; i++)
6260 {
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006261 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
6262 for (j = 0; j < temp; j++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006263 {
6264 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
6265 {
6266 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
6267 break;
6268 }
6269 }
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006270 if ((j < temp) && (currentRate > maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006271 {
6272 maxRate = currentRate;
6273 maxSpeedMCS = 1;
6274 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
6275 }
6276 }
6277 }
6278
6279 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006280 if (((maxRate < myRate) && (0 == rssidx)) ||
6281 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006282 {
6283 maxRate = myRate;
6284 if (rate_flags & eHAL_TX_RATE_LEGACY)
6285 {
6286 maxSpeedMCS = 0;
6287 }
6288 else
6289 {
6290 maxSpeedMCS = 1;
6291 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6292 }
6293 }
6294
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006295 if ((!maxSpeedMCS) || (0 != rssidx))
Jeff Johnson295189b2012-06-20 16:38:30 -07006296 {
6297 sinfo->txrate.legacy = maxRate;
6298#ifdef LINKSPEED_DEBUG_ENABLED
6299 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
6300#endif //LINKSPEED_DEBUG_ENABLED
6301 }
6302 else
6303 {
6304 sinfo->txrate.mcs = maxMCSIdx;
6305 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6306 if (rate_flags & eHAL_TX_RATE_SGI)
6307 {
6308 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6309 }
6310 if (rate_flags & eHAL_TX_RATE_HT40)
6311 {
6312 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6313 }
6314#ifdef LINKSPEED_DEBUG_ENABLED
6315 pr_info("Reporting MCS rate %d flags %x\n",
6316 sinfo->txrate.mcs,
6317 sinfo->txrate.flags );
6318#endif //LINKSPEED_DEBUG_ENABLED
6319 }
6320 }
6321 else
6322 {
6323 // report current rate instead of max rate
6324
6325 if (rate_flags & eHAL_TX_RATE_LEGACY)
6326 {
6327 //provide to the UI in units of 100kbps
6328 sinfo->txrate.legacy = myRate;
6329#ifdef LINKSPEED_DEBUG_ENABLED
6330 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
6331#endif //LINKSPEED_DEBUG_ENABLED
6332 }
6333 else
6334 {
6335 //must be MCS
6336 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6337 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6338 if (rate_flags & eHAL_TX_RATE_SGI)
6339 {
6340 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6341 }
6342 if (rate_flags & eHAL_TX_RATE_HT40)
6343 {
6344 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6345 }
6346#ifdef LINKSPEED_DEBUG_ENABLED
6347 pr_info("Reporting actual MCS rate %d flags %x\n",
6348 sinfo->txrate.mcs,
6349 sinfo->txrate.flags );
6350#endif //LINKSPEED_DEBUG_ENABLED
6351 }
6352 }
6353 sinfo->filled |= STATION_INFO_TX_BITRATE;
6354
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006355 sinfo->tx_packets =
6356 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
6357 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
6358 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
6359 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
6360
6361 sinfo->tx_retries =
6362 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
6363 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
6364 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
6365 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
6366
6367 sinfo->tx_failed =
6368 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
6369 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
6370 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
6371 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
6372
6373 sinfo->filled |=
6374 STATION_INFO_TX_PACKETS |
6375 STATION_INFO_TX_RETRIES |
6376 STATION_INFO_TX_FAILED;
6377
6378 EXIT();
6379 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006380}
6381
6382static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
6383 struct net_device *dev, bool mode, v_SINT_t timeout)
6384{
6385 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6386 VOS_STATUS vos_status;
6387
Jeff Johnsone7245742012-09-05 17:12:55 -07006388 ENTER();
6389
Jeff Johnson295189b2012-06-20 16:38:30 -07006390 if (NULL == pAdapter)
6391 {
6392 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6393 return -ENODEV;
6394 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006395 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6396 {
6397 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6398 "%s:LOGP in Progress. Ignore!!!", __func__);
6399 return -EAGAIN;
6400 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006401
6402 /**The get power cmd from the supplicant gets updated by the nl only
6403 *on successful execution of the function call
6404 *we are oppositely mapped w.r.t mode in the driver
6405 **/
6406 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
6407
Jeff Johnsone7245742012-09-05 17:12:55 -07006408 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006409 if (VOS_STATUS_E_FAILURE == vos_status)
6410 {
6411 return -EINVAL;
6412 }
6413 return 0;
6414}
6415
6416
6417#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6418static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
6419 struct net_device *netdev,
6420 u8 key_index)
6421{
Jeff Johnsone7245742012-09-05 17:12:55 -07006422 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006423 return 0;
6424}
6425#endif //LINUX_VERSION_CODE
6426
6427#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
6428static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6429 struct net_device *dev,
6430 struct ieee80211_txq_params *params)
6431{
Jeff Johnsone7245742012-09-05 17:12:55 -07006432 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006433 return 0;
6434}
6435#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6436static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6437 struct ieee80211_txq_params *params)
6438{
Jeff Johnsone7245742012-09-05 17:12:55 -07006439 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006440 return 0;
6441}
6442#endif //LINUX_VERSION_CODE
6443
6444static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
6445 struct net_device *dev, u8 *mac)
6446{
6447 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006448 VOS_STATUS vos_status;
6449 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006450
Jeff Johnsone7245742012-09-05 17:12:55 -07006451 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006452 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6453 {
6454 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6455 return -EINVAL;
6456 }
6457
6458 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6459 {
6460 hddLog( LOGE,
6461 "%s: Wlan Load/Unload is in progress", __func__);
6462 return -EBUSY;
6463 }
6464
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006465 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6466 {
6467 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6468 "%s:LOGP in Progress. Ignore!!!", __func__);
6469 return -EAGAIN;
6470 }
6471
Jeff Johnson295189b2012-06-20 16:38:30 -07006472 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006473 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006474 )
6475 {
6476 if( NULL == mac )
6477 {
6478 v_U16_t i;
6479 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
6480 {
6481 if(pAdapter->aStaInfo[i].isUsed)
6482 {
6483 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
6484 hddLog(VOS_TRACE_LEVEL_INFO,
6485 "%s: Delete STA with MAC::"
6486 "%02x:%02x:%02x:%02x:%02x:%02x",
6487 __func__,
6488 macAddr[0], macAddr[1], macAddr[2],
6489 macAddr[3], macAddr[4], macAddr[5]);
6490 hdd_softap_sta_deauth(pAdapter, macAddr);
6491 }
6492 }
6493 }
6494 else
6495 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006496
6497 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
6498 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6499 {
6500 hddLog(VOS_TRACE_LEVEL_INFO,
6501 "%s: Skip this DEL STA as this is not used::"
6502 "%02x:%02x:%02x:%02x:%02x:%02x",
6503 __func__,
6504 mac[0], mac[1], mac[2],
6505 mac[3], mac[4], mac[5]);
6506 return -ENOENT;
6507 }
6508
6509 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
6510 {
6511 hddLog(VOS_TRACE_LEVEL_INFO,
6512 "%s: Skip this DEL STA as deauth is in progress::"
6513 "%02x:%02x:%02x:%02x:%02x:%02x",
6514 __func__,
6515 mac[0], mac[1], mac[2],
6516 mac[3], mac[4], mac[5]);
6517 return -ENOENT;
6518 }
6519
6520 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
6521
Jeff Johnson295189b2012-06-20 16:38:30 -07006522 hddLog(VOS_TRACE_LEVEL_INFO,
6523 "%s: Delete STA with MAC::"
6524 "%02x:%02x:%02x:%02x:%02x:%02x",
6525 __func__,
6526 mac[0], mac[1], mac[2],
6527 mac[3], mac[4], mac[5]);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006528
6529 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
6530 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6531 {
6532 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
6533 hddLog(VOS_TRACE_LEVEL_INFO,
6534 "%s: STA removal failed for ::"
6535 "%02x:%02x:%02x:%02x:%02x:%02x",
6536 __func__,
6537 mac[0], mac[1], mac[2],
6538 mac[3], mac[4], mac[5]);
6539 return -ENOENT;
6540 }
6541
Jeff Johnson295189b2012-06-20 16:38:30 -07006542 }
6543 }
6544
6545 EXIT();
6546
6547 return 0;
6548}
6549
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006550static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
6551 struct net_device *dev, u8 *mac, struct station_parameters *params)
6552{
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006553 int status = -EPERM;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006554#ifdef FEATURE_WLAN_TDLS
6555 u32 mask, set;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006556 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006557 mask = params->sta_flags_mask;
6558
6559 set = params->sta_flags_set;
6560
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006561#ifdef WLAN_FEATURE_TDLS_DEBUG
6562 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6563 "%s: mask 0x%x set 0x%x " MAC_ADDRESS_STR,
6564 __func__, mask, set, MAC_ADDR_ARRAY(mac));
6565#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006566
6567 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6568 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006569 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006570 }
6571 }
6572#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006573 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006574}
6575
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006576
6577#ifdef FEATURE_WLAN_LFR
6578static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006579 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006580{
6581#define MAX_PMKSAIDS_IN_CACHE 8
6582 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -07006583 static tANI_U32 i; // HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006584 tANI_U32 j=0;
6585 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6586 tHalHandle halHandle;
6587 eHalStatus result;
6588 tANI_U8 BSSIDMatched = 0;
6589
Jeff Johnsone7245742012-09-05 17:12:55 -07006590 ENTER();
6591
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006592 // Validate pAdapter
6593 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6594 {
6595 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6596 return -EINVAL;
6597 }
6598
6599 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6600 {
6601 hddLog( LOGE,
6602 "%s: Wlan Load/Unload is in progress", __func__);
6603 return -EBUSY;
6604 }
6605
6606 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6607 {
6608 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6609 "%s:LOGP in Progress. Ignore!!!", __func__);
6610 return -EAGAIN;
6611 }
6612
6613 // Retrieve halHandle
6614 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
6615
6616 for (j = 0; j < i; j++)
6617 {
6618 if(vos_mem_compare(PMKIDCache[j].BSSID,
6619 pmksa->bssid, WNI_CFG_BSSID_LEN))
6620 {
6621 /* BSSID matched previous entry. Overwrite it. */
6622 BSSIDMatched = 1;
6623 vos_mem_copy(PMKIDCache[j].BSSID,
6624 pmksa->bssid, WNI_CFG_BSSID_LEN);
6625 vos_mem_copy(PMKIDCache[j].PMKID,
6626 pmksa->pmkid,
6627 CSR_RSN_PMKID_SIZE);
6628 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006629 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006630 dump_bssid(pmksa->bssid);
6631 dump_pmkid(halHandle, pmksa->pmkid);
6632 break;
6633 }
6634 }
6635
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07006636 /* Check we compared all entries,if then take the first slot now */
6637 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
6638
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006639 if (!BSSIDMatched)
6640 {
6641 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
6642 vos_mem_copy(PMKIDCache[i].BSSID,
6643 pmksa->bssid, ETHER_ADDR_LEN);
6644 vos_mem_copy(PMKIDCache[i].PMKID,
6645 pmksa->pmkid,
6646 CSR_RSN_PMKID_SIZE);
6647 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006648 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006649 dump_bssid(pmksa->bssid);
6650 dump_pmkid(halHandle, pmksa->pmkid);
6651 // Increment the HDD Local Cache index
6652 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
6653 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
6654 }
6655
6656
6657 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
6658 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006659 // __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006660 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006661 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006662 // Finally set the PMKSA ID Cache in CSR
6663 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
6664 PMKIDCache,
6665 i );
6666 return 0;
6667}
6668
6669
6670static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006671 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006672{
Jeff Johnsone7245742012-09-05 17:12:55 -07006673 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006674 // TODO: Implement this later.
6675 return 0;
6676}
6677
6678static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
6679{
Jeff Johnsone7245742012-09-05 17:12:55 -07006680 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006681 // TODO: Implement this later.
6682 return 0;
6683}
6684#endif
6685
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006686#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6687static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
6688 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
6689{
6690 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6691 hdd_station_ctx_t *pHddStaCtx;
6692
6693 if (NULL == pAdapter)
6694 {
6695 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6696 return -ENODEV;
6697 }
6698
6699 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6700
6701 // Added for debug on reception of Re-assoc Req.
6702 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6703 {
6704 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
6705 ftie->ie_len);
6706 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
6707 }
6708
6709#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
6710 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
6711 ftie->ie_len);
6712#endif
6713
6714 // Pass the received FT IEs to SME
6715 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, ftie->ie,
6716 ftie->ie_len);
6717 return 0;
6718}
6719#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006720
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006721#ifdef FEATURE_WLAN_TDLS
6722static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
6723 u8 *peer, u8 action_code, u8 dialog_token,
6724 u16 status_code, const u8 *buf, size_t len)
6725{
6726
6727 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6728 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006729 u8 peerMac[6];
6730 VOS_STATUS status;
Gopichand Nakkala05922802013-03-14 12:23:19 -07006731 int max_sta_failed = 0;
Hoonki Leea34dd892013-02-05 22:56:02 -08006732 int responder;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006733
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006734 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006735 {
6736 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6737 "Invalid arguments");
6738 return -EINVAL;
6739 }
6740
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006741 if (pHddCtx->isLogpInProgress)
6742 {
6743 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6744 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006745 wlan_hdd_tdls_set_link_status(pAdapter, peer, eTDLS_LINK_IDLE);
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006746 return -EBUSY;
6747 }
6748
Hoonki Lee27511902013-03-14 18:19:06 -07006749 if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006750 {
Hoonki Lee27511902013-03-14 18:19:06 -07006751 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6752 "%s: TDLS mode is disabled OR not enabled in FW."
6753 MAC_ADDRESS_STR " action %d declined.",
6754 __func__, MAC_ADDR_ARRAY(peer), action_code);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006755 return -ENOTSUPP;
6756 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006757
Hoonki Lee27511902013-03-14 18:19:06 -07006758 if ((SIR_MAC_TDLS_SETUP_RSP == action_code) ||
6759 (SIR_MAC_TDLS_DIS_RSP == action_code))
6760 {
6761 wlan_hdd_tdls_set_cap (pAdapter, peerMac, eTDLS_CAP_SUPPORTED);
6762 }
6763
6764 /* other than teardown frame, other mgmt frames are not sent if disabled */
6765 if (SIR_MAC_TDLS_TEARDOWN != action_code)
6766 {
6767 /* if tdls_mode is disabled to respond to peer's request */
6768 if (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode)
6769 {
6770 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6771 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006772 " TDLS mode is disabled. action %d declined.",
6773 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee27511902013-03-14 18:19:06 -07006774
6775 return -ENOTSUPP;
6776 }
6777 }
6778
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006779 if (WLAN_IS_TDLS_SETUP_ACTION(action_code))
6780 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006781 if (wlan_hdd_tdls_is_progress(pAdapter, peer, TRUE))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006782 {
6783 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006784 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006785 " TDLS setup is ongoing. action %d declined.",
6786 __func__, MAC_ADDR_ARRAY(peer), action_code);
6787 return -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006788 }
6789 }
6790
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006791 if (SIR_MAC_TDLS_SETUP_REQ == action_code ||
6792 SIR_MAC_TDLS_SETUP_RSP == action_code )
Lee Hoonkic1262f22013-01-24 21:59:00 -08006793 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006794 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
Lee Hoonkic1262f22013-01-24 21:59:00 -08006795 {
6796 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
6797 we return error code at 'add_station()'. Hence we have this
6798 check again in addtion to add_station().
6799 Anyway, there is no hard to double-check. */
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006800 if (SIR_MAC_TDLS_SETUP_REQ == action_code)
Lee Hoonkic1262f22013-01-24 21:59:00 -08006801 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006802 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6803 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006804 " TDLS Max peer already connected. action %d declined.",
6805 __func__, MAC_ADDR_ARRAY(peer), action_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006806 goto error;
Lee Hoonkic1262f22013-01-24 21:59:00 -08006807 }
6808 else
6809 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006810 /* maximum reached. tweak to send error code to peer and return
6811 error code to supplicant */
Lee Hoonkic1262f22013-01-24 21:59:00 -08006812 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006813 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6814 "%s: " MAC_ADDRESS_STR
6815 " TDLS Max peer already connected send response status %d",
6816 __func__, MAC_ADDR_ARRAY(peer), status_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006817 max_sta_failed = -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006818 /* fall through to send setup resp with failure status
6819 code */
Lee Hoonkic1262f22013-01-24 21:59:00 -08006820 }
6821 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006822 else
6823 {
6824 hddTdlsPeer_t *pTdlsPeer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006825 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006826 if (pTdlsPeer && (eTDLS_LINK_CONNECTED == pTdlsPeer->link_status))
6827 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006828 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006829 "%s:" MAC_ADDRESS_STR " already connected. action %d declined.",
6830 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006831 return -EPERM;
6832 }
6833 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006834 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006835 vos_mem_copy(peerMac, peer, 6);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006836
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006837#ifdef WLAN_FEATURE_TDLS_DEBUG
6838 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006839 "%s: " MAC_ADDRESS_STR " action %d, dialog_token %d status %d, len = %d",
6840 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
6841 action_code, dialog_token, status_code, len);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006842#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006843
Hoonki Leea34dd892013-02-05 22:56:02 -08006844 /*Except teardown responder will not be used so just make 0*/
6845 responder = 0;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006846 if (SIR_MAC_TDLS_TEARDOWN == action_code)
Hoonki Leea34dd892013-02-05 22:56:02 -08006847 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006848 responder = wlan_hdd_tdls_get_responder(pAdapter, peerMac);
6849 if(-1 == responder)
Hoonki Leea34dd892013-02-05 22:56:02 -08006850 {
6851 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006852 "%s: " MAC_ADDRESS_STR " peer doesn't exist dialog_token %d status %d, len = %d",
6853 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
Hoonki Leea34dd892013-02-05 22:56:02 -08006854 dialog_token, status_code, len);
6855 return -EPERM;
6856 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006857 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006858
Gopichand Nakkala05922802013-03-14 12:23:19 -07006859 /* max_sta_failed ; we didn't set to CONNECTING for this case,
6860 because we already know that this transaction will be failed,
6861 but we weren't sure if supplicant call DISABLE_LINK or not. So,
6862 to be safe, do not change the state mahine.
6863 */
6864 if (max_sta_failed == 0 &&
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006865 (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
Gopichand Nakkala8b00c632013-03-08 19:47:52 -08006866 wlan_hdd_tdls_set_link_status(pAdapter, peerMac, eTDLS_LINK_CONNECTING);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006867
6868 INIT_COMPLETION(pAdapter->tdls_mgmt_comp);
6869
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006870 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
Hoonki Leea34dd892013-02-05 22:56:02 -08006871 peerMac, action_code, dialog_token, status_code, (tANI_U8 *)buf, len, responder);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006872
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006873 if (VOS_STATUS_SUCCESS != status)
6874 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006875 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6876 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006877 return -EPERM;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006878 }
6879
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006880 /* not block discovery request, as it is called from timer callback */
6881 if (SIR_MAC_TDLS_DIS_REQ != action_code)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006882 {
Pervinder Singhb4638422013-03-04 22:51:36 -08006883 long rc;
6884
6885 rc = wait_for_completion_interruptible_timeout(&pAdapter->tdls_mgmt_comp,
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006886 msecs_to_jiffies(WAIT_TIME_TDLS_MGMT));
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006887
Pervinder Singhb4638422013-03-04 22:51:36 -08006888 if ((rc <= 0) || (TRUE != pAdapter->mgmtTxCompletionStatus))
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006889 {
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006890 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pervinder Singhb4638422013-03-04 22:51:36 -08006891 "%s: Mgmt Tx Completion failed status %ld TxCompletion %lu",
6892 __func__, rc, pAdapter->mgmtTxCompletionStatus);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006893 return -EPERM;
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006894 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006895 }
6896
Gopichand Nakkala05922802013-03-14 12:23:19 -07006897 if (max_sta_failed)
6898 return max_sta_failed;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006899
Hoonki Leea34dd892013-02-05 22:56:02 -08006900 if (SIR_MAC_TDLS_SETUP_RSP == action_code)
6901 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006902 wlan_hdd_tdls_set_responder(pAdapter, peerMac, TRUE);
Hoonki Leea34dd892013-02-05 22:56:02 -08006903 }
6904 else if (SIR_MAC_TDLS_SETUP_CNF == action_code)
6905 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006906 wlan_hdd_tdls_set_responder(pAdapter, peerMac, FALSE);
Hoonki Leea34dd892013-02-05 22:56:02 -08006907 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006908
6909 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07006910error:
6911 /* max_sta_failed ; we didn't set to CONNECTING for this case,
6912 because we already know that this transaction will be failed,
6913 but we weren't sure if supplicant call DISABLE_LINK or not. So,
6914 to be safe, do not change the state mahine.
6915 */
6916 if(max_sta_failed == 0 &&
6917 (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
6918 wlan_hdd_tdls_set_link_status(pAdapter, peerMac, eTDLS_LINK_IDLE);
6919 return -EPERM;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006920}
6921
6922static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
6923 u8 *peer, enum nl80211_tdls_operation oper)
6924{
6925 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6926 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006927#ifdef WLAN_FEATURE_TDLS_DEBUG
6928 const char *tdls_oper_str[]= {
6929 "NL80211_TDLS_DISCOVERY_REQ",
6930 "NL80211_TDLS_SETUP",
6931 "NL80211_TDLS_TEARDOWN",
6932 "NL80211_TDLS_ENABLE_LINK",
6933 "NL80211_TDLS_DISABLE_LINK",
6934 "NL80211_TDLS_UNKONW_OPER"};
6935#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006936
6937 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6938 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006939 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006940 "Invalid arguments");
6941 return -EINVAL;
6942 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006943
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006944 if (pHddCtx->isLogpInProgress)
6945 {
6946 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6947 "%s:LOGP in Progress. Ignore!!!", __func__);
6948 return -EBUSY;
6949 }
6950
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006951#ifdef WLAN_FEATURE_TDLS_DEBUG
6952 if((int)oper > 4)
6953 oper = 5;
6954
6955 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006956 "%s: " MAC_ADDRESS_STR " %d (%s) ", "tdls_oper",
6957 MAC_ADDR_ARRAY(peer), (int)oper,
6958 tdls_oper_str[(int)oper]);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006959#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006960
6961 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006962 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006963 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006964 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006965 "TDLS Disabled in INI OR not enabled in FW.\
6966 Cannot process TDLS commands \n");
6967 return -ENOTSUPP;
6968 }
6969
6970 switch (oper) {
6971 case NL80211_TDLS_ENABLE_LINK:
6972 {
Hoonki Lee387663d2013-02-05 18:08:43 -08006973 hddTdlsPeer_t *pTdlsPeer;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006974 VOS_STATUS status;
6975
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006976 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006977
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006978 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
6979 "%s: TDLS_LINK_ENABLE " MAC_ADDRESS_STR,
6980 __func__, MAC_ADDR_ARRAY(peer));
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006981
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006982 if ( NULL == pTdlsPeer ) {
6983 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_hdd_tdls_find_peer "
6984 MAC_ADDRESS_STR " failed",
6985 __func__, MAC_ADDR_ARRAY(peer));
6986 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006987 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006988
6989 if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status)
6990 {
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07006991 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006992 /* start TDLS client registration with TL */
6993 status = hdd_roamRegisterTDLSSTA( pAdapter, peer, pTdlsPeer->staId, pTdlsPeer->signature);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07006994 if (VOS_STATUS_SUCCESS == status)
6995 {
6996 wlan_hdd_tdls_increment_peer_count(pAdapter);
6997 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006998 wlan_hdd_tdls_check_bmps(pAdapter);
6999 }
7000
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007001 }
7002 break;
7003 case NL80211_TDLS_DISABLE_LINK:
Lee Hoonkic1262f22013-01-24 21:59:00 -08007004 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007005 hddTdlsPeer_t *curr_peer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007006
7007 if(NULL != curr_peer)
Lee Hoonkic1262f22013-01-24 21:59:00 -08007008 {
7009 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
7010 pAdapter->sessionId, peer );
Gopichand Nakkala8b00c632013-03-08 19:47:52 -08007011 wlan_hdd_tdls_set_peer_link_status(curr_peer, eTDLS_LINK_IDLE);
Lee Hoonkic1262f22013-01-24 21:59:00 -08007012 }
7013 else
7014 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007015 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7016 "%s: TDLS Peer Station doesn't exist.", __func__);
Lee Hoonkic1262f22013-01-24 21:59:00 -08007017 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08007018 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007019 break;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007020 case NL80211_TDLS_TEARDOWN:
7021 case NL80211_TDLS_SETUP:
7022 case NL80211_TDLS_DISCOVERY_REQ:
7023 /* We don't support in-driver setup/teardown/discovery */
7024 return -ENOTSUPP;
7025 default:
7026 return -ENOTSUPP;
7027 }
7028 return 0;
7029}
Chilam NG571c65a2013-01-19 12:27:36 +05307030
7031int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
7032 struct net_device *dev, u8 *peer)
7033{
7034 hddLog(VOS_TRACE_LEVEL_INFO, "tdls send discover req: %x %x %x %x %x %x",
7035 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5]);
7036
7037 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
7038 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
7039}
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007040#endif
7041
Jeff Johnson295189b2012-06-20 16:38:30 -07007042/* cfg80211_ops */
7043static struct cfg80211_ops wlan_hdd_cfg80211_ops =
7044{
7045 .add_virtual_intf = wlan_hdd_add_virtual_intf,
7046 .del_virtual_intf = wlan_hdd_del_virtual_intf,
7047 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
7048 .change_station = wlan_hdd_change_station,
7049#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
7050 .add_beacon = wlan_hdd_cfg80211_add_beacon,
7051 .del_beacon = wlan_hdd_cfg80211_del_beacon,
7052 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007053#else
7054 .start_ap = wlan_hdd_cfg80211_start_ap,
7055 .change_beacon = wlan_hdd_cfg80211_change_beacon,
7056 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07007057#endif
7058 .change_bss = wlan_hdd_cfg80211_change_bss,
7059 .add_key = wlan_hdd_cfg80211_add_key,
7060 .get_key = wlan_hdd_cfg80211_get_key,
7061 .del_key = wlan_hdd_cfg80211_del_key,
7062 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08007063#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07007064 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08007065#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007066 .scan = wlan_hdd_cfg80211_scan,
7067 .connect = wlan_hdd_cfg80211_connect,
7068 .disconnect = wlan_hdd_cfg80211_disconnect,
7069 .join_ibss = wlan_hdd_cfg80211_join_ibss,
7070 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
7071 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
7072 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
7073 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
Jeff Johnson295189b2012-06-20 16:38:30 -07007074 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
7075 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
7076 .mgmt_tx = wlan_hdd_action,
7077#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7078 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
7079 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
7080 .set_txq_params = wlan_hdd_set_txq_params,
7081#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007082 .get_station = wlan_hdd_cfg80211_get_station,
7083 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
7084 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007085 .add_station = wlan_hdd_cfg80211_add_station,
7086#ifdef FEATURE_WLAN_LFR
7087 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
7088 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
7089 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
7090#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007091#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
7092 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
7093#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007094#ifdef FEATURE_WLAN_TDLS
7095 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
7096 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
7097#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007098};
7099