blob: e1fffb77943233b494ebe3438df8e651154e2a86 [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 }
2709 if (pHddCtx->isLogpInProgress)
2710 {
2711 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2712 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07002713 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002714 return -EBUSY;
2715 }
2716
2717 if (FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
2718 FALSE == sme_IsFeatureSupportedByFW(TDLS))
2719 {
2720 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2721 "TDLS Disabled in INI OR not enabled in FW.\
2722 Cannot process TDLS commands \n");
2723 return -ENOTSUPP;
2724 }
2725
2726 if (wlan_hdd_tdls_is_progress(pAdapter, mac, TRUE))
2727 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002728 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2729 "%s: " MAC_ADDRESS_STR
2730 " TDLS setup is ongoing. Request declined.",
2731 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002732 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002733 }
2734
2735 /* first to check if we reached to maximum supported TDLS peer.
2736 TODO: for now, return -EPERM looks working fine,
2737 but need to check if any other errno fit into this category.*/
2738 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
2739 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002740 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2741 "%s: " MAC_ADDRESS_STR
2742 " TDLS Max peer already connected. Request declined.",
2743 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002744 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002745 }
2746 else
2747 {
2748 hddTdlsPeer_t *pTdlsPeer;
2749 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac);
2750 if (pTdlsPeer && (eTDLS_LINK_CONNECTED == pTdlsPeer->link_status))
2751 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002752 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2753 "%s: " MAC_ADDRESS_STR " already connected. Request declined.",
2754 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002755 return -EPERM;
2756 }
2757 }
2758
2759 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_CONNECTING);
2760
2761 INIT_COMPLETION(pAdapter->tdls_add_station_comp);
2762
2763 if (!update)
2764 {
2765 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
2766 pAdapter->sessionId, mac);
2767 }
2768 else
2769 {
2770 status = sme_ChangeTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
2771 pAdapter->sessionId, mac, StaParams);
2772 }
2773
2774 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_add_station_comp,
2775 msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
2776
2777 if (!status)
2778 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002779 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002780 "%s: timeout waiting for tdls add station indication",
2781 __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07002782 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002783 }
2784 if ( eHAL_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus)
2785 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002786 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002787 "%s: Add Station is unsucessful", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07002788 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002789 }
2790
2791 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07002792
2793error:
2794 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
2795 return -EPERM;
2796
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002797}
2798#endif
2799
Jeff Johnson295189b2012-06-20 16:38:30 -07002800static int wlan_hdd_change_station(struct wiphy *wiphy,
2801 struct net_device *dev,
2802 u8 *mac,
2803 struct station_parameters *params)
2804{
2805 VOS_STATUS status = VOS_STATUS_SUCCESS;
2806 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2807 v_MACADDR_t STAMacAddress;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002808#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002809 tCsrStaParams StaParams = {0};
2810 u32 set;
2811 tANI_U8 isBufSta = 0;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002812#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07002813 ENTER();
2814
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002815 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2816 {
2817 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2818 "%s:LOGP in Progress. Ignore!!!", __func__);
2819 return -EAGAIN;
2820 }
2821
Jeff Johnson295189b2012-06-20 16:38:30 -07002822 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
2823
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002824#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002825 StaParams.capability = params->capability;
2826 StaParams.uapsd_queues = params->uapsd_queues;
2827 StaParams.max_sp = params->max_sp;
2828
2829 if (0 != params->ext_capab_len)
2830 vos_mem_copy(StaParams.extn_capability, params->ext_capab,
2831 sizeof(StaParams.extn_capability));
2832
2833 if (NULL != params->ht_capa)
2834 vos_mem_copy(&StaParams.HTCap, params->ht_capa, sizeof(tSirHTCap));
2835
2836 StaParams.supported_rates_len = params->supported_rates_len;
2837
2838 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
2839 * The supported_rates array , for all the structures propogating till Add Sta
2840 * to the firmware has to be modified , if the supplicant (ieee80211) is
2841 * modified to send more rates.
2842 */
2843
2844 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
2845 */
2846 if (StaParams.supported_rates_len > SIR_MAC_MAX_SUPP_RATES)
2847 StaParams.supported_rates_len = SIR_MAC_MAX_SUPP_RATES;
2848
2849 if (0 != StaParams.supported_rates_len) {
2850 int i = 0;
2851 vos_mem_copy(StaParams.supported_rates, params->supported_rates,
2852 StaParams.supported_rates_len);
2853 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2854 "Supported Rates with Length %d", StaParams.supported_rates_len);
2855 for (i=0; i < StaParams.supported_rates_len; i++)
2856 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2857 "[%d]: %0x", i, StaParams.supported_rates[i]);
2858 }
2859
2860 if (NULL != params->vht_capa)
2861 vos_mem_copy(&StaParams.VHTCap, params->vht_capa, sizeof(tSirVHTCap));
2862
2863 set = params->sta_flags_set;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002864#endif
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002865
2866 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2867 || (pAdapter->device_mode == WLAN_HDD_P2P_GO))
Jeff Johnson295189b2012-06-20 16:38:30 -07002868 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002869 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
Jeff Johnson295189b2012-06-20 16:38:30 -07002870 {
2871 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
2872 WLANTL_STA_AUTHENTICATED);
2873
2874 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002875 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002876 return -EINVAL;
2877 }
2878 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002879#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002880 else if (pAdapter->device_mode == WLAN_HDD_INFRA_STATION ) {
2881 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
2882 if (0 != params->ext_capab_len ) {
2883 /*Define A Macro : TODO Sunil*/
2884 if ((1<<4) & StaParams.extn_capability[3]) {
2885 isBufSta = 1;
2886 }
2887 }
2888 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2889 "%s: TDLS Peer Parameters.", __func__);
2890 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2891 "uapsd_queues: %0x\n", params->uapsd_queues);
2892 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2893 "max_sp: %0x\n", params->max_sp);
2894 if (params->ht_capa) {
2895 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2896 "ht_capa->cap_info: %0x\n", params->ht_capa->cap_info);
2897 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2898 "ht_capa->ampdu_params_info: %0x\n",
2899 params->ht_capa->ampdu_params_info);
2900 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2901 "ht_capa->extended_capabilities: %0x\n",
2902 params->ht_capa->extended_ht_cap_info);
2903 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2904 "ht_capa->tx_BF_cap_info: %0x\n",
2905 params->ht_capa->tx_BF_cap_info);
2906 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2907 "ht_capa->antenna_selection_info: %0x\n",
2908 params->ht_capa->antenna_selection_info);
2909 }
2910 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2911 "params->capability: %0x\n",params->capability);
2912 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2913 "params->ext_capab_len: %0x\n",params->ext_capab_len);
2914 if (0 != params->ext_capab_len )
2915 {
2916 int i =0;
2917 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2918 "Extended capabilities:");
2919 for (i=0; i < params->ext_capab_len; i++)
2920 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2921 "[%d]: %0x", i, params->ext_capab[i]);
2922 }
2923 //status = wlan_hdd_tdls_set_peer_caps( mac, params->uapsd_queues,
2924 // params->max_sp, isBufSta);
2925 if (VOS_STATUS_SUCCESS != status) {
2926 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2927 "%s: wlan_hdd_tdls_set_peer_caps failed!", __func__);
2928 return -EINVAL;
2929 }
2930 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2931 "ht_capa->cap_info: %0x\n", StaParams.HTCap.capInfo);
2932 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 1, &StaParams);
2933
2934 if (VOS_STATUS_SUCCESS != status) {
2935 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2936 "%s: sme_ChangeTdlsPeerSta failed!", __func__);
2937 return -EINVAL;
2938 }
2939 }
2940 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002941#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002942
Jeff Johnsone7245742012-09-05 17:12:55 -07002943 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002944 return status;
2945}
2946
2947/*
2948 * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
2949 * This function is used to get peer station index in IBSS mode
2950 */
2951static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
2952{
2953 u8 idx = 0;
2954 u8 temp[VOS_MAC_ADDR_SIZE] = {0};
2955 ENTER();
2956 memset(temp, 0, VOS_MAC_ADDR_SIZE);
2957 for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
2958 {
2959 if ( (0 !=
2960 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
2961 && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
2962 temp, VOS_MAC_ADDR_SIZE)
2963 )
2964 {
2965 return idx;
2966 }
2967 }
2968 return idx;
2969}
2970
2971
2972/*
2973 * FUNCTION: wlan_hdd_cfg80211_add_key
2974 * This function is used to initialize the key information
2975 */
2976#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2977static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2978 struct net_device *ndev,
2979 u8 key_index, bool pairwise,
2980 const u8 *mac_addr,
2981 struct key_params *params
2982 )
2983#else
2984static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2985 struct net_device *ndev,
2986 u8 key_index, const u8 *mac_addr,
2987 struct key_params *params
2988 )
2989#endif
2990{
2991 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2992 tCsrRoamSetKey setKey;
2993 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
2994 int status = 0;
2995 v_U32_t roamId= 0xFF;
2996 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2997 hdd_hostapd_state_t *pHostapdState;
2998 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07002999 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07003000
3001 ENTER();
3002
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003003 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3004 {
3005 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3006 "%s:LOGP in Progress. Ignore!!!", __func__);
3007 return -EAGAIN;
3008 }
3009
Jeff Johnson295189b2012-06-20 16:38:30 -07003010 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3011 __func__,pAdapter->device_mode);
3012
3013 if (CSR_MAX_NUM_KEY <= key_index)
3014 {
3015 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3016 key_index);
3017
3018 return -EINVAL;
3019 }
3020
3021 hddLog(VOS_TRACE_LEVEL_INFO,
3022 "%s: called with key index = %d & key length %d",
3023 __func__, key_index, params->key_len);
3024
3025 /*extract key idx, key len and key*/
3026 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3027 setKey.keyId = key_index;
3028 setKey.keyLength = params->key_len;
3029 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
3030
3031 switch (params->cipher)
3032 {
3033 case WLAN_CIPHER_SUITE_WEP40:
3034 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
3035 break;
3036
3037 case WLAN_CIPHER_SUITE_WEP104:
3038 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
3039 break;
3040
3041 case WLAN_CIPHER_SUITE_TKIP:
3042 {
3043 u8 *pKey = &setKey.Key[0];
3044 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
3045
3046 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
3047
3048 /*Supplicant sends the 32bytes key in this order
3049
3050 |--------------|----------|----------|
3051 | Tk1 |TX-MIC | RX Mic |
3052 |--------------|----------|----------|
3053 <---16bytes---><--8bytes--><--8bytes-->
3054
3055 */
3056 /*Sme expects the 32 bytes key to be in the below order
3057
3058 |--------------|----------|----------|
3059 | Tk1 |RX-MIC | TX Mic |
3060 |--------------|----------|----------|
3061 <---16bytes---><--8bytes--><--8bytes-->
3062 */
3063 /* Copy the Temporal Key 1 (TK1) */
3064 vos_mem_copy(pKey, params->key,16);
3065
3066 /*Copy the rx mic first*/
3067 vos_mem_copy(&pKey[16],&params->key[24],8);
3068
3069 /*Copy the tx mic */
3070 vos_mem_copy(&pKey[24],&params->key[16],8);
3071
3072
3073 break;
3074 }
3075
3076 case WLAN_CIPHER_SUITE_CCMP:
3077 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
3078 break;
3079
3080#ifdef FEATURE_WLAN_WAPI
3081 case WLAN_CIPHER_SUITE_SMS4:
3082 {
3083 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3084 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
3085 params->key, params->key_len);
3086 return 0;
3087 }
3088#endif
3089#ifdef FEATURE_WLAN_CCX
3090 case WLAN_CIPHER_SUITE_KRK:
3091 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
3092 break;
3093#endif
3094 default:
3095 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
3096 __func__, params->cipher);
3097 return -EOPNOTSUPP;
3098 }
3099
3100 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
3101 __func__, setKey.encType);
3102
3103
3104
3105 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003106 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07003107 )
3108 {
3109
3110
3111 if (
3112#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3113 (!pairwise)
3114#else
3115 (!mac_addr || is_broadcast_ether_addr(mac_addr))
3116#endif
3117 )
3118 {
3119 /* set group key*/
3120 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson1250df42012-12-10 14:31:52 -08003121 "%s- %d: setting Broadcast key",
Jeff Johnson295189b2012-06-20 16:38:30 -07003122 __func__, __LINE__);
3123 setKey.keyDirection = eSIR_RX_ONLY;
3124 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3125 }
3126 else
3127 {
3128 /* set pairwise key*/
3129 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3130 "%s- %d: setting pairwise key",
3131 __func__, __LINE__);
3132 setKey.keyDirection = eSIR_TX_RX;
3133 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3134 }
3135
3136 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3137 if( pHostapdState->bssState == BSS_START )
3138 {
3139 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3140
3141 if ( status != eHAL_STATUS_SUCCESS )
3142 {
3143 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3144 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3145 __LINE__, status );
3146 }
3147 }
3148
3149 /* Saving WEP keys */
3150 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
3151 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
3152 {
3153 //Save the wep key in ap context. Issue setkey after the BSS is started.
3154 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3155 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
3156 }
3157 else
3158 {
3159 //Save the key in ap context. Issue setkey after the BSS is started.
3160 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3161 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
3162 }
3163 }
3164 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003165 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003166 )
3167 {
3168 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3169 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3170
3171 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
3172
Venkata Prathyusha Kuntupalliee2ce712013-01-17 14:09:24 -08003173 pWextState->roamProfile.Keys.defaultIndex = key_index;
3174
3175
Jeff Johnson295189b2012-06-20 16:38:30 -07003176 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
3177 params->key, params->key_len);
3178
3179 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3180
3181 if (!( ( IW_AUTH_KEY_MGMT_802_1X
3182 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
3183 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3184 )
3185 &&
3186 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3187 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3188 )
3189 )
3190 {
3191 /* in case of static WEP, macaddr/bssid is not coming from nl80211
3192 * interface, copy bssid for pairwise key and group macaddr for
3193 * group key initialization*/
3194
3195 tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
3196
3197 pWextState->roamProfile.negotiatedUCEncryptionType =
3198 pHddStaCtx->conn_info.ucEncryptionType =
3199 ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
3200 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
3201 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
3202
3203
3204 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3205 "%s: Negotiated encryption type %d", __func__,
3206 pWextState->roamProfile.negotiatedUCEncryptionType);
3207
3208 sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
3209 &pWextState->roamProfile, true);
3210 setKey.keyLength = 0;
3211 setKey.keyDirection = eSIR_TX_RX;
3212
3213#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3214 if (pairwise)
3215 {
3216#endif
3217 if (mac_addr)
3218 {
3219 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3220 }
3221 else
3222 {
3223 /* macaddr is NULL, set the peerMac to bssId in case of BSS,
3224 * and peerMacAddress in case of IBSS*/
3225 if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
3226 {
3227 u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
3228 if (HDD_MAX_NUM_IBSS_STA != staidx)
3229 {
3230 vos_mem_copy(setKey.peerMac,
3231 &pHddStaCtx->conn_info.peerMacAddress[staidx],
3232 WNI_CFG_BSSID_LEN);
3233
3234 }
3235 else
3236 {
3237 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
3238 __func__);
3239 return -EOPNOTSUPP;
3240 }
3241 }
3242 else
3243 {
3244 vos_mem_copy(setKey.peerMac,
3245 &pHddStaCtx->conn_info.bssId[0],
3246 WNI_CFG_BSSID_LEN);
3247 }
3248 }
3249#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3250 }
3251 else
3252 {
3253 /* set group key*/
3254 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3255 "%s- %d: setting Group key",
3256 __func__, __LINE__);
3257 setKey.keyDirection = eSIR_RX_ONLY;
3258 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3259 }
3260#endif
3261 }
3262 else if (
3263#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3264 (!pairwise)
3265#else
3266 (!mac_addr || is_broadcast_ether_addr(mac_addr))
3267#endif
3268 )
3269 {
3270 /* set group key*/
3271 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3272 "%s- %d: setting Group key",
3273 __func__, __LINE__);
3274 setKey.keyDirection = eSIR_RX_ONLY;
3275 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3276 }
3277 else
3278 {
3279 /* set pairwise key*/
3280 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3281 "%s- %d: setting pairwise key",
3282 __func__, __LINE__);
3283 setKey.keyDirection = eSIR_TX_RX;
3284 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3285 }
3286
3287 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3288 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3289 __func__, setKey.peerMac[0], setKey.peerMac[1],
3290 setKey.peerMac[2], setKey.peerMac[3],
3291 setKey.peerMac[4], setKey.peerMac[5],
3292 setKey.keyDirection);
3293
3294 vos_status = wlan_hdd_check_ula_done(pAdapter);
3295
3296 if ( vos_status != VOS_STATUS_SUCCESS )
3297 {
3298 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3299 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
3300 __LINE__, vos_status );
3301
3302 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3303
3304 return -EINVAL;
3305
3306 }
3307
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003308#ifdef WLAN_FEATURE_VOWIFI_11R
3309 /* The supplicant may attempt to set the PTK once pre-authentication is done.
3310 Save the key in the UMAC and include it in the ADD BSS request */
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003311 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303312 if( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_WAIT )
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003313 {
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303314 return -EINVAL;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003315 }
3316#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07003317
3318 /* issue set key request to SME*/
3319 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3320 pAdapter->sessionId, &setKey, &roamId );
3321
3322 if ( 0 != status )
3323 {
3324 hddLog(VOS_TRACE_LEVEL_ERROR,
3325 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3326 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3327 return -EINVAL;
3328 }
3329
3330
3331 /* in case of IBSS as there was no information available about WEP keys during
3332 * IBSS join, group key intialized with NULL key, so re-initialize group key
3333 * with correct value*/
3334 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
3335 !( ( IW_AUTH_KEY_MGMT_802_1X
3336 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
3337 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3338 )
3339 &&
3340 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3341 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3342 )
3343 )
3344 {
3345 setKey.keyDirection = eSIR_RX_ONLY;
3346 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3347
3348 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3349 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3350 __func__, setKey.peerMac[0], setKey.peerMac[1],
3351 setKey.peerMac[2], setKey.peerMac[3],
3352 setKey.peerMac[4], setKey.peerMac[5],
3353 setKey.keyDirection);
3354
3355 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3356 pAdapter->sessionId, &setKey, &roamId );
3357
3358 if ( 0 != status )
3359 {
3360 hddLog(VOS_TRACE_LEVEL_ERROR,
3361 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
3362 __func__, status);
3363 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3364 return -EINVAL;
3365 }
3366 }
3367 }
3368
3369 return 0;
3370}
3371
3372/*
3373 * FUNCTION: wlan_hdd_cfg80211_get_key
3374 * This function is used to get the key information
3375 */
3376#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3377static int wlan_hdd_cfg80211_get_key(
3378 struct wiphy *wiphy,
3379 struct net_device *ndev,
3380 u8 key_index, bool pairwise,
3381 const u8 *mac_addr, void *cookie,
3382 void (*callback)(void *cookie, struct key_params*)
3383 )
3384#else
3385static int wlan_hdd_cfg80211_get_key(
3386 struct wiphy *wiphy,
3387 struct net_device *ndev,
3388 u8 key_index, const u8 *mac_addr, void *cookie,
3389 void (*callback)(void *cookie, struct key_params*)
3390 )
3391#endif
3392{
3393 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3394 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3395 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
3396 struct key_params params;
3397
3398 ENTER();
3399
3400 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3401 __func__,pAdapter->device_mode);
3402
3403 memset(&params, 0, sizeof(params));
3404
3405 if (CSR_MAX_NUM_KEY <= key_index)
3406 {
3407 return -EINVAL;
3408 }
3409
3410 switch(pRoamProfile->EncryptionType.encryptionType[0])
3411 {
3412 case eCSR_ENCRYPT_TYPE_NONE:
3413 params.cipher = IW_AUTH_CIPHER_NONE;
3414 break;
3415
3416 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3417 case eCSR_ENCRYPT_TYPE_WEP40:
3418 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3419 break;
3420
3421 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3422 case eCSR_ENCRYPT_TYPE_WEP104:
3423 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3424 break;
3425
3426 case eCSR_ENCRYPT_TYPE_TKIP:
3427 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3428 break;
3429
3430 case eCSR_ENCRYPT_TYPE_AES:
3431 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3432 break;
3433
3434 default:
3435 params.cipher = IW_AUTH_CIPHER_NONE;
3436 break;
3437 }
3438
3439 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3440 params.seq_len = 0;
3441 params.seq = NULL;
3442 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3443 callback(cookie, &params);
3444 return 0;
3445}
3446
3447/*
3448 * FUNCTION: wlan_hdd_cfg80211_del_key
3449 * This function is used to delete the key information
3450 */
3451#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3452static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3453 struct net_device *ndev,
3454 u8 key_index,
3455 bool pairwise,
3456 const u8 *mac_addr
3457 )
3458#else
3459static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3460 struct net_device *ndev,
3461 u8 key_index,
3462 const u8 *mac_addr
3463 )
3464#endif
3465{
3466 int status = 0;
3467
3468 //This code needs to be revisited. There is sme_removeKey API, we should
3469 //plan to use that. After the change to use correct index in setkey,
3470 //it is observed that this is invalidating peer
3471 //key index whenever re-key is done. This is affecting data link.
3472 //It should be ok to ignore del_key.
3473#if 0
3474 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3475 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
3476 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3477 tCsrRoamSetKey setKey;
3478 v_U32_t roamId= 0xFF;
3479
3480 ENTER();
3481
3482 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3483 __func__,pAdapter->device_mode);
3484
3485 if (CSR_MAX_NUM_KEY <= key_index)
3486 {
3487 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3488 key_index);
3489
3490 return -EINVAL;
3491 }
3492
3493 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3494 setKey.keyId = key_index;
3495
3496 if (mac_addr)
3497 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3498 else
3499 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3500
3501 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3502
3503 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003504 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07003505 )
3506 {
3507
3508 hdd_hostapd_state_t *pHostapdState =
3509 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3510 if( pHostapdState->bssState == BSS_START)
3511 {
3512 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3513
3514 if ( status != eHAL_STATUS_SUCCESS )
3515 {
3516 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3517 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3518 __LINE__, status );
3519 }
3520 }
3521 }
3522 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003523 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003524 )
3525 {
3526 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3527
3528 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3529
3530 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3531 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
3532 __func__, setKey.peerMac[0], setKey.peerMac[1],
3533 setKey.peerMac[2], setKey.peerMac[3],
3534 setKey.peerMac[4], setKey.peerMac[5]);
3535 if(pAdapter->sessionCtx.station.conn_info.connState ==
3536 eConnectionState_Associated)
3537 {
3538 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3539 pAdapter->sessionId, &setKey, &roamId );
3540
3541 if ( 0 != status )
3542 {
3543 hddLog(VOS_TRACE_LEVEL_ERROR,
3544 "%s: sme_RoamSetKey failure, returned %d",
3545 __func__, status);
3546 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3547 return -EINVAL;
3548 }
3549 }
3550 }
3551#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003552 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003553 return status;
3554}
3555
3556/*
3557 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3558 * This function is used to set the default tx key index
3559 */
3560#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3561static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3562 struct net_device *ndev,
3563 u8 key_index,
3564 bool unicast, bool multicast)
3565#else
3566static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3567 struct net_device *ndev,
3568 u8 key_index)
3569#endif
3570{
3571 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3572 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3573 int status = 0;
3574 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3575
3576 ENTER();
3577
3578 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3579 __func__,pAdapter->device_mode, key_index);
3580
3581 if (CSR_MAX_NUM_KEY <= key_index)
3582 {
3583 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3584 key_index);
3585
3586 return -EINVAL;
3587 }
3588
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003589 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3590 {
3591 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3592 "%s:LOGP in Progress. Ignore!!!", __func__);
3593 return -EAGAIN;
3594 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003595
3596 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003597 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003598 )
3599 {
3600 if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
3601 (eCSR_ENCRYPT_TYPE_TKIP !=
3602 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3603 (eCSR_ENCRYPT_TYPE_AES !=
3604 pWextState->roamProfile.EncryptionType.encryptionType[0])
3605 )
3606 {
3607 /* if default key index is not same as previous one,
3608 * then update the default key index */
3609
3610 tCsrRoamSetKey setKey;
3611 v_U32_t roamId= 0xFF;
3612 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
3613
3614 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
3615 __func__, key_index);
3616
3617 Keys->defaultIndex = (u8)key_index;
3618 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3619 setKey.keyId = key_index;
3620 setKey.keyLength = Keys->KeyLength[key_index];
3621
3622 vos_mem_copy(&setKey.Key[0],
3623 &Keys->KeyMaterial[key_index][0],
3624 Keys->KeyLength[key_index]);
3625
3626 setKey.keyDirection = eSIR_TX_ONLY;
3627
3628 vos_mem_copy(setKey.peerMac,
3629 &pHddStaCtx->conn_info.bssId[0],
3630 WNI_CFG_BSSID_LEN);
3631
3632 setKey.encType =
3633 pWextState->roamProfile.EncryptionType.encryptionType[0];
3634
3635 /* issue set key request */
3636 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3637 pAdapter->sessionId, &setKey, &roamId );
3638
3639 if ( 0 != status )
3640 {
3641 hddLog(VOS_TRACE_LEVEL_ERROR,
3642 "%s: sme_RoamSetKey failed, returned %d", __func__,
3643 status);
3644 return -EINVAL;
3645 }
3646 }
3647 }
3648
3649 /* In SoftAp mode setting key direction for default mode */
3650 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3651 {
3652 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3653 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3654 (eCSR_ENCRYPT_TYPE_AES !=
3655 pWextState->roamProfile.EncryptionType.encryptionType[0])
3656 )
3657 {
3658 /* Saving key direction for default key index to TX default */
3659 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3660 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3661 }
3662 }
3663
3664 return status;
3665}
3666
Jeff Johnson295189b2012-06-20 16:38:30 -07003667/*
3668 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3669 * This function is used to inform the BSS details to nl80211 interface.
3670 */
3671static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3672 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3673{
3674 struct net_device *dev = pAdapter->dev;
3675 struct wireless_dev *wdev = dev->ieee80211_ptr;
3676 struct wiphy *wiphy = wdev->wiphy;
3677 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3678 int chan_no;
3679 int ie_length;
3680 const char *ie;
3681 unsigned int freq;
3682 struct ieee80211_channel *chan;
3683 int rssi = 0;
3684 struct cfg80211_bss *bss = NULL;
3685
3686 ENTER();
3687
3688 if( NULL == pBssDesc )
3689 {
3690 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3691 return bss;
3692 }
3693
3694 chan_no = pBssDesc->channelId;
3695 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3696 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3697
3698 if( NULL == ie )
3699 {
3700 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3701 return bss;
3702 }
3703
3704#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3705 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3706 {
3707 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3708 }
3709 else
3710 {
3711 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3712 }
3713#else
3714 freq = ieee80211_channel_to_frequency(chan_no);
3715#endif
3716
3717 chan = __ieee80211_get_channel(wiphy, freq);
3718
3719 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3720 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3721 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3722 if (bss == NULL)
3723 {
3724 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3725
3726 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3727 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3728 pBssDesc->capabilityInfo,
3729 pBssDesc->beaconInterval, ie, ie_length,
3730 rssi, GFP_KERNEL ));
3731}
3732 else
3733 {
3734 return bss;
3735 }
3736}
3737
3738
3739
3740/*
3741 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3742 * This function is used to inform the BSS details to nl80211 interface.
3743 */
3744struct cfg80211_bss*
3745wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3746 tSirBssDescription *bss_desc
3747 )
3748{
3749 /*
3750 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3751 already exists in bss data base of cfg80211 for that particular BSS ID.
3752 Using cfg80211_inform_bss_frame to update the bss entry instead of
3753 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3754 now there is no possibility to get the mgmt(probe response) frame from PE,
3755 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3756 cfg80211_inform_bss_frame.
3757 */
3758 struct net_device *dev = pAdapter->dev;
3759 struct wireless_dev *wdev = dev->ieee80211_ptr;
3760 struct wiphy *wiphy = wdev->wiphy;
3761 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003762#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3763 qcom_ie_age *qie_age = NULL;
3764 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3765#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003766 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003767#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003768 const char *ie =
3769 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3770 unsigned int freq;
3771 struct ieee80211_channel *chan;
3772 struct ieee80211_mgmt *mgmt =
3773 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3774 struct cfg80211_bss *bss_status = NULL;
3775 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3776 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003777#ifdef WLAN_OPEN_SOURCE
3778 struct timespec ts;
3779#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003780
3781 ENTER();
3782
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003783 if (!mgmt)
3784 return NULL;
3785
Jeff Johnson295189b2012-06-20 16:38:30 -07003786 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003787
3788#ifdef WLAN_OPEN_SOURCE
3789 /* Android does not want the timestamp from the frame.
3790 Instead it wants a monotonic increasing value */
3791 get_monotonic_boottime(&ts);
3792 mgmt->u.probe_resp.timestamp =
3793 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3794#else
3795 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003796 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3797 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003798
3799#endif
3800
Jeff Johnson295189b2012-06-20 16:38:30 -07003801 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3802 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003803
3804#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3805 /* GPS Requirement: need age ie per entry. Using vendor specific. */
3806 /* Assuming this is the last IE, copy at the end */
3807 ie_length -=sizeof(qcom_ie_age);
3808 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
3809 qie_age->element_id = QCOM_VENDOR_IE_ID;
3810 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
3811 qie_age->oui_1 = QCOM_OUI1;
3812 qie_age->oui_2 = QCOM_OUI2;
3813 qie_age->oui_3 = QCOM_OUI3;
3814 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
3815 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
3816#endif
3817
Jeff Johnson295189b2012-06-20 16:38:30 -07003818 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3819
3820 mgmt->frame_control |=
3821 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3822
3823#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3824 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3825 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3826 {
3827 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3828 }
3829 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3830 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3831
3832 {
3833 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3834 }
3835 else
3836 {
3837 kfree(mgmt);
3838 return NULL;
3839 }
3840#else
3841 freq = ieee80211_channel_to_frequency(chan_no);
3842#endif
3843 chan = __ieee80211_get_channel(wiphy, freq);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08003844 /*when the band is changed on the fly using the GUI, three things are done
3845 * 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)
3846 * as part of the scan abort, message willbe queued to PE and we proceed with flushing and changinh the band.
3847 * pe will stop the scanning further and report back the results what ever it had till now by calling the call back function.
3848 * if the time between update band and scandone call back is sufficent enough the band change reflects in SME, SME validates the channels
3849 * and discards the channels correponding to previous band and calls back with zero bss results.
3850 * 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
3851 * all the channels correponding to previous band.this is due to race condition.but those channels are invalid to the new band and so
3852 * this function __ieee80211_get_channel will return NULL.Each time we report scan result with this pointer null warning kernel trace is printed.
3853 * if the scan results contain large number of APs continuosly kernel warning trace is printed and it will lead to apps watch dog bark.
3854 * So drop the bss and continue to next bss.
3855 */
3856 if(chan == NULL)
3857 {
3858 hddLog(VOS_TRACE_LEVEL_INFO, "%s chan pointer is NULL", __func__);
3859 return NULL;
3860 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003861 /*To keep the rssi icon of the connected AP in the scan window
3862 *and the rssi icon of the wireless networks in sync
3863 * */
3864 if (( eConnectionState_Associated ==
3865 pAdapter->sessionCtx.station.conn_info.connState ) &&
3866 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3867 pAdapter->sessionCtx.station.conn_info.bssId,
3868 WNI_CFG_BSSID_LEN)))
3869 {
3870 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3871 rssi = (pAdapter->rssi * 100);
3872 }
3873 else
3874 {
3875 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3876 }
3877
3878 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3879 frame_len, rssi, GFP_KERNEL);
3880 kfree(mgmt);
3881 return bss_status;
3882}
3883
3884/*
3885 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3886 * This function is used to update the BSS data base of CFG8011
3887 */
3888struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3889 tCsrRoamInfo *pRoamInfo
3890 )
3891{
3892 tCsrRoamConnectedProfile roamProfile;
3893 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3894 struct cfg80211_bss *bss = NULL;
3895
3896 ENTER();
3897
3898 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
3899 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
3900
3901 if (NULL != roamProfile.pBssDesc)
3902 {
3903 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
3904 &roamProfile);
3905
3906 if (NULL == bss)
3907 {
3908 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
3909 __func__);
3910 }
3911
3912 sme_RoamFreeConnectProfile(hHal, &roamProfile);
3913 }
3914 else
3915 {
3916 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
3917 __func__);
3918 }
3919 return bss;
3920}
3921
3922/*
3923 * FUNCTION: wlan_hdd_cfg80211_update_bss
3924 */
3925static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
3926 hdd_adapter_t *pAdapter
3927 )
3928{
3929 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3930 tCsrScanResultInfo *pScanResult;
3931 eHalStatus status = 0;
3932 tScanResultHandle pResult;
3933 struct cfg80211_bss *bss_status = NULL;
3934
3935 ENTER();
3936
3937 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3938 {
3939 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3940 return -EAGAIN;
3941 }
3942
3943 /*
3944 * start getting scan results and populate cgf80211 BSS database
3945 */
3946 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
3947
3948 /* no scan results */
3949 if (NULL == pResult)
3950 {
3951 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
3952 return status;
3953 }
3954
3955 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
3956
3957 while (pScanResult)
3958 {
3959 /*
3960 * cfg80211_inform_bss() is not updating ie field of bss entry, if
3961 * entry already exists in bss data base of cfg80211 for that
3962 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
3963 * bss entry instead of cfg80211_inform_bss, But this call expects
3964 * mgmt packet as input. As of now there is no possibility to get
3965 * the mgmt(probe response) frame from PE, converting bss_desc to
3966 * ieee80211_mgmt(probe response) and passing to c
3967 * fg80211_inform_bss_frame.
3968 * */
3969
3970 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
3971 &pScanResult->BssDescriptor);
3972
3973
3974 if (NULL == bss_status)
3975 {
3976 hddLog(VOS_TRACE_LEVEL_INFO,
3977 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
3978 }
3979 else
3980 {
3981 cfg80211_put_bss(bss_status);
3982 }
3983
3984 pScanResult = sme_ScanResultGetNext(hHal, pResult);
3985 }
3986
3987 sme_ScanResultPurge(hHal, pResult);
3988
3989 return 0;
3990}
3991
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003992void
3993hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
3994{
3995 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003996 "%02X:%02X:%02X:%02X:%02X:%02X\n",
3997 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
3998 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003999} /****** end hddPrintMacAddr() ******/
4000
4001void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004002hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004003{
4004 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004005 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
4006 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
4007 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
4008 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004009} /****** end hddPrintPmkId() ******/
4010
4011//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
4012//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
4013
4014//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
4015//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
4016
4017#define dump_bssid(bssid) \
4018 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004019 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
4020 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
4021 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004022 }
4023
4024#define dump_pmkid(pMac, pmkid) \
4025 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004026 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
4027 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
4028 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004029 }
4030
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07004031#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004032/*
4033 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
4034 * This function is used to notify the supplicant of a new PMKSA candidate.
4035 */
4036int wlan_hdd_cfg80211_pmksa_candidate_notify(
4037 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
4038 int index, bool preauth )
4039{
Jeff Johnsone7245742012-09-05 17:12:55 -07004040#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004041 struct net_device *dev = pAdapter->dev;
4042
4043 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07004044 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004045
4046 if( NULL == pRoamInfo )
4047 {
4048 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
4049 return -EINVAL;
4050 }
4051
4052 dump_bssid(pRoamInfo->bssid);
4053 cfg80211_pmksa_candidate_notify(dev, index,
4054 pRoamInfo->bssid, preauth, GFP_KERNEL);
Jeff Johnsone7245742012-09-05 17:12:55 -07004055#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004056 return 0;
4057}
4058#endif //FEATURE_WLAN_LFR
4059
Jeff Johnson295189b2012-06-20 16:38:30 -07004060/*
4061 * FUNCTION: hdd_cfg80211_scan_done_callback
4062 * scanning callback function, called after finishing scan
4063 *
4064 */
4065static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
4066 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
4067{
4068 struct net_device *dev = (struct net_device *) pContext;
4069 //struct wireless_dev *wdev = dev->ieee80211_ptr;
4070 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004071 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4072 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004073 struct cfg80211_scan_request *req = NULL;
4074 int ret = 0;
4075
4076 ENTER();
4077
4078 hddLog(VOS_TRACE_LEVEL_INFO,
4079 "%s called with halHandle = %p, pContext = %p,"
4080 "scanID = %d, returned status = %d\n",
4081 __func__, halHandle, pContext, (int) scanId, (int) status);
4082
4083 //Block on scan req completion variable. Can't wait forever though.
4084 ret = wait_for_completion_interruptible_timeout(
4085 &pScanInfo->scan_req_completion_event,
4086 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
4087 if (!ret)
4088 {
4089 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004090 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004091 }
4092
4093 if(pScanInfo->mScanPending != VOS_TRUE)
4094 {
4095 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004096 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004097 }
4098
4099 /* Check the scanId */
4100 if (pScanInfo->scanId != scanId)
4101 {
4102 hddLog(VOS_TRACE_LEVEL_INFO,
4103 "%s called with mismatched scanId pScanInfo->scanId = %d "
4104 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
4105 (int) scanId);
4106 }
4107
Jeff Johnson295189b2012-06-20 16:38:30 -07004108 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
4109 pAdapter);
4110
4111 if (0 > ret)
4112 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
4113
4114
4115 /* If any client wait scan result through WEXT
4116 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004117 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07004118 {
4119 /* The other scan request waiting for current scan finish
4120 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004121 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004122 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004123 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004124 }
4125 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004126 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004127 {
4128 struct net_device *dev = pAdapter->dev;
4129 union iwreq_data wrqu;
4130 int we_event;
4131 char *msg;
4132
4133 memset(&wrqu, '\0', sizeof(wrqu));
4134 we_event = SIOCGIWSCAN;
4135 msg = NULL;
4136 wireless_send_event(dev, we_event, &wrqu, msg);
4137 }
4138 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004139 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004140
4141 /* Get the Scan Req */
4142 req = pAdapter->request;
4143
4144 if (!req)
4145 {
4146 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004147 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07004148 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004149 }
4150
4151 /*
4152 * setting up 0, just in case.
4153 */
4154 req->n_ssids = 0;
4155 req->n_channels = 0;
4156 req->ie = 0;
4157
Jeff Johnson295189b2012-06-20 16:38:30 -07004158 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004159 /* Scan is no longer pending */
4160 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004161
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07004162 /*
4163 * cfg80211_scan_done informing NL80211 about completion
4164 * of scanning
4165 */
4166 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004167 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004168
Jeff Johnsone7245742012-09-05 17:12:55 -07004169allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004170 /* release the wake lock at the end of the scan*/
4171 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004172
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004173 /* Acquire wakelock to handle the case where APP's tries to suspend
4174 * immediatly after the driver gets connect request(i.e after scan)
4175 * from supplicant, this result in app's is suspending and not able
4176 * to process the connect request to AP */
4177 hdd_allow_suspend_timeout(100);
4178
Jeff Johnson295189b2012-06-20 16:38:30 -07004179 EXIT();
4180 return 0;
4181}
4182
4183/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004184 * FUNCTION: hdd_isScanAllowed
4185 * Go through each adapter and check if scan allowed
4186 *
4187 */
4188v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
4189{
4190 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4191 hdd_station_ctx_t *pHddStaCtx = NULL;
4192 hdd_adapter_t *pAdapter = NULL;
4193 VOS_STATUS status = 0;
4194 v_U8_t staId = 0;
4195 v_U8_t *staMac = NULL;
4196
4197 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4198
4199 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4200 {
4201 pAdapter = pAdapterNode->pAdapter;
4202
4203 if( pAdapter )
4204 {
4205 hddLog(VOS_TRACE_LEVEL_INFO,
4206 "%s: Adapter with device mode %d exists",
4207 __func__, pAdapter->device_mode);
4208 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4209 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4210 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
4211 {
4212 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4213 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
4214 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
4215 {
4216 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
4217 hddLog(VOS_TRACE_LEVEL_ERROR,
4218 "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the "
4219 "middle of WPS/EAPOL exchange.", __func__,
4220 staMac[0], staMac[1], staMac[2],
4221 staMac[3], staMac[4], staMac[5]);
4222 return VOS_FALSE;
4223 }
4224 }
4225 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
4226 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
4227 {
4228 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
4229 {
4230 if ((pAdapter->aStaInfo[staId].isUsed) &&
4231 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
4232 {
4233 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
4234
4235 hddLog(VOS_TRACE_LEVEL_ERROR,
4236 "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the "
4237 "middle of WPS/EAPOL exchange.", __func__,
4238 staMac[0], staMac[1], staMac[2],
4239 staMac[3], staMac[4], staMac[5]);
4240 return VOS_FALSE;
4241 }
4242 }
4243 }
4244 }
4245 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4246 pAdapterNode = pNext;
4247 }
4248 hddLog(VOS_TRACE_LEVEL_INFO,
4249 "%s: Scan allowed", __func__);
4250 return VOS_TRUE;
4251}
4252
4253/*
Jeff Johnson295189b2012-06-20 16:38:30 -07004254 * FUNCTION: wlan_hdd_cfg80211_scan
4255 * this scan respond to scan trigger and update cfg80211 scan database
4256 * later, scan dump command can be used to recieve scan results
4257 */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08004258int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
4259#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4260 struct net_device *dev,
4261#endif
4262 struct cfg80211_scan_request *request)
4263{
4264#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4265 struct net_device *dev = request->wdev->netdev;
4266#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004267 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4268 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4269 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4270 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
4271 tCsrScanRequest scanRequest;
4272 tANI_U8 *channelList = NULL, i;
4273 v_U32_t scanId = 0;
4274 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004275 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004276 v_U8_t* pP2pIe = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004277
4278 ENTER();
4279
4280 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4281 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004282
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004283 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004284 (eConnectionState_Connecting ==
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004285 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004286 {
4287 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004288 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
4289 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004290 return -EBUSY;
4291 }
4292
Jeff Johnson295189b2012-06-20 16:38:30 -07004293#ifdef WLAN_BTAMP_FEATURE
4294 //Scan not supported when AMP traffic is on.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004295 if (VOS_TRUE == WLANBAP_AmpSessionOn())
Jeff Johnson295189b2012-06-20 16:38:30 -07004296 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004297 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004298 "%s: No scanning when AMP is on", __func__);
4299 return -EOPNOTSUPP;
4300 }
4301#endif
4302 //Scan on any other interface is not supported.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004303 if (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07004304 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004305 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004306 "%s: Not scanning on device_mode = %d",
4307 __func__, pAdapter->device_mode);
4308 return -EOPNOTSUPP;
4309 }
4310
4311 if (TRUE == pScanInfo->mScanPending)
4312 {
4313 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004314 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07004315 }
4316
4317 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4318 {
4319 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4320 "%s:LOGP in Progress. Ignore!!!", __func__);
4321 return -EAGAIN;
4322 }
4323
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07004324 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
4325 {
4326 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4327 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
4328 return -EAGAIN;
4329 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004330 //Don't Allow Scan and return busy if Remain On
4331 //Channel and action frame is pending
4332 //Otherwise Cancel Remain On Channel and allow Scan
4333 //If no action frame pending
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004334 if (0 != wlan_hdd_check_remain_on_channel(pAdapter))
Jeff Johnson32d95a32012-09-10 13:15:23 -07004335 {
4336 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
4337 return -EBUSY;
4338 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004339#ifdef FEATURE_WLAN_TDLS
4340 if (wlan_hdd_tdlsConnectedPeers(pAdapter))
4341 {
4342 tANI_U8 staIdx;
4343
4344 for (staIdx = 0; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
4345 {
4346 if (pHddCtx->tdlsConnInfo[staIdx].staId)
4347 {
4348 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4349 ("scan: indicate TDLS teadown (staId %d)"), pHddCtx->tdlsConnInfo[staIdx].staId) ;
4350
4351#ifdef CONFIG_TDLS_IMPLICIT
4352 cfg80211_tdls_oper_request(pAdapter->dev,
4353 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes,
4354 NL80211_TDLS_TEARDOWN,
4355 eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON,
4356 GFP_KERNEL);
4357#endif
4358 }
4359 }
4360 return -EBUSY;
4361 }
4362#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07004363
Jeff Johnson295189b2012-06-20 16:38:30 -07004364 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
4365 {
4366 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08004367 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004368 return -EAGAIN;
4369 }
4370 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
4371 {
4372 hddLog(VOS_TRACE_LEVEL_WARN,
4373 "%s: MAX TM Level Scan not allowed", __func__);
4374 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4375 return -EBUSY;
4376 }
4377 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4378
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004379 /* Check if scan is allowed at this point of time.
4380 */
4381 if (!hdd_isScanAllowed(pHddCtx))
4382 {
4383 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
4384 return -EBUSY;
4385 }
4386
Jeff Johnson295189b2012-06-20 16:38:30 -07004387 vos_mem_zero( &scanRequest, sizeof(scanRequest));
4388
4389 if (NULL != request)
4390 {
4391 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
4392 (int)request->n_ssids);
4393
4394 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
4395 * Becasue of this, driver is assuming that this is not wildcard scan and so
4396 * is not aging out the scan results.
4397 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07004398 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07004399 {
4400 request->n_ssids = 0;
4401 }
4402
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004403 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07004404 {
4405 tCsrSSIDInfo *SsidInfo;
4406 int j;
4407 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
4408 /* Allocate num_ssid tCsrSSIDInfo structure */
4409 SsidInfo = scanRequest.SSIDs.SSIDList =
4410 ( tCsrSSIDInfo *)vos_mem_malloc(
4411 request->n_ssids*sizeof(tCsrSSIDInfo));
4412
4413 if(NULL == scanRequest.SSIDs.SSIDList)
4414 {
4415 hddLog(VOS_TRACE_LEVEL_ERROR,
4416 "memory alloc failed SSIDInfo buffer");
4417 return -ENOMEM;
4418 }
4419
4420 /* copy all the ssid's and their length */
4421 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
4422 {
4423 /* get the ssid length */
4424 SsidInfo->SSID.length = request->ssids[j].ssid_len;
4425 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
4426 SsidInfo->SSID.length);
4427 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
4428 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
4429 j, SsidInfo->SSID.ssId);
4430 }
4431 /* set the scan type to active */
4432 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4433 }
4434 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4435 {
4436 /* set the scan type to active */
4437 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4438 }
4439 else
4440 {
4441 /*Set the scan type to default type, in this case it is ACTIVE*/
4442 scanRequest.scanType = pScanInfo->scan_mode;
4443 }
4444 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
4445 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4446 }
4447 else
4448 {
4449 /* set the scan type to active */
4450 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4451 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4452
4453 /* set min and max channel time to zero */
4454 scanRequest.minChnTime = 0;
4455 scanRequest.maxChnTime = 0;
4456 }
4457
4458 /* set BSSType to default type */
4459 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4460
4461 /*TODO: scan the requested channels only*/
4462
4463 /*Right now scanning all the channels */
4464 if( request )
4465 {
4466 if( request->n_channels )
4467 {
4468 channelList = vos_mem_malloc( request->n_channels );
4469 if( NULL == channelList )
4470 {
4471 status = -ENOMEM;
4472 goto free_mem;
4473 }
4474
4475 for( i = 0 ; i < request->n_channels ; i++ )
4476 channelList[i] = request->channels[i]->hw_value;
4477 }
4478
4479 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4480 scanRequest.ChannelInfo.ChannelList = channelList;
4481
4482 /* set requestType to full scan */
4483 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004484
4485 /* Flush the scan results(only p2p beacons) for STA scan and P2P
4486 * search (Flush on both full scan and social scan but not on single
4487 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
4488 */
4489
4490 /* Supplicant does single channel scan after 8-way handshake
4491 * and in that case driver shoudnt flush scan results. If
4492 * driver flushes the scan results here and unfortunately if
4493 * the AP doesnt respond to our probe req then association
4494 * fails which is not desired
4495 */
4496
4497 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4498 {
4499 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4500 pAdapter->sessionId );
4501 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004502
4503 if( request->ie_len )
4504 {
4505 /* save this for future association (join requires this) */
4506 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4507 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4508 pScanInfo->scanAddIE.length = request->ie_len;
4509
4510 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004511 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4512 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004513 )
4514 {
4515 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4516 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4517 }
4518
4519 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4520 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4521
Jeff Johnson295189b2012-06-20 16:38:30 -07004522 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4523 request->ie_len);
4524 if (pP2pIe != NULL)
4525 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004526#ifdef WLAN_FEATURE_P2P_DEBUG
4527 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4528 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4529 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4530 {
4531 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4532 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4533 "Go nego completed to Connection is started");
4534 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4535 "for 8way Handshake");
4536 }
4537 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4538 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4539 {
4540 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4541 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4542 "Disconnected state to Connection is started");
4543 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4544 "for 4way Handshake");
4545 }
4546#endif
4547
Jeff Johnsone7245742012-09-05 17:12:55 -07004548 /* no_cck will be set during p2p find to disable 11b rates */
4549 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004550 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004551 hddLog(VOS_TRACE_LEVEL_INFO,
4552 "%s: This is a P2P Search", __func__);
4553 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004554
Jeff Johnsone7245742012-09-05 17:12:55 -07004555 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4556 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004557 /* set requestType to P2P Discovery */
4558 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004559 }
4560
4561 /*
4562 Skip Dfs Channel in case of P2P Search
4563 if it is set in ini file
4564 */
4565 if(cfg_param->skipDfsChnlInP2pSearch)
4566 {
4567 scanRequest.skipDfsChnlInP2pSearch = 1;
4568 }
4569 else
4570 {
4571 scanRequest.skipDfsChnlInP2pSearch = 0;
4572 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004573
Jeff Johnson295189b2012-06-20 16:38:30 -07004574 }
4575 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004576 }
4577 }
4578
4579 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4580
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004581 /* acquire the wakelock to avoid the apps suspend during the scan. To
4582 * address the following issues.
4583 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4584 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4585 * for long time, this result in apps running at full power for long time.
4586 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4587 * be stuck in full power because of resume BMPS
4588 */
4589 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004590
4591 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004592 pAdapter->sessionId, &scanRequest, &scanId,
4593 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004594
Jeff Johnson295189b2012-06-20 16:38:30 -07004595 if (eHAL_STATUS_SUCCESS != status)
4596 {
4597 hddLog(VOS_TRACE_LEVEL_ERROR,
4598 "%s: sme_ScanRequest returned error %d", __func__, status);
4599 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004600 if(eHAL_STATUS_RESOURCES == status)
4601 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004602 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 -07004603 status = -EBUSY;
4604 } else {
4605 status = -EIO;
4606 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004607 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004608 goto free_mem;
4609 }
4610
4611 pScanInfo->mScanPending = TRUE;
4612 pAdapter->request = request;
4613 pScanInfo->scanId = scanId;
4614
4615 complete(&pScanInfo->scan_req_completion_event);
4616
4617free_mem:
4618 if( scanRequest.SSIDs.SSIDList )
4619 {
4620 vos_mem_free(scanRequest.SSIDs.SSIDList);
4621 }
4622
4623 if( channelList )
4624 vos_mem_free( channelList );
4625
4626 EXIT();
4627
4628 return status;
4629}
4630
4631/*
4632 * FUNCTION: wlan_hdd_cfg80211_connect_start
4633 * This function is used to start the association process
4634 */
4635int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004636 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004637{
4638 int status = 0;
4639 hdd_wext_state_t *pWextState;
4640 v_U32_t roamId;
4641 tCsrRoamProfile *pRoamProfile;
4642 eMib_dot11DesiredBssType connectedBssType;
4643 eCsrAuthType RSNAuthType;
4644
4645 ENTER();
4646
4647 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4648
4649 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4650 {
4651 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4652 return -EINVAL;
4653 }
4654
4655 pRoamProfile = &pWextState->roamProfile;
4656
4657 if (pRoamProfile)
4658 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004659 int ret = 0;
4660 hdd_station_ctx_t *pHddStaCtx;
4661 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4662 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4663
4664 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4665 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4666 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004667 {
4668 /* Issue disconnect to CSR */
4669 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4670 if( eHAL_STATUS_SUCCESS ==
4671 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4672 pAdapter->sessionId,
4673 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4674 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004675 ret = wait_for_completion_interruptible_timeout(
4676 &pAdapter->disconnect_comp_var,
4677 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4678 if (0 == ret)
4679 {
4680 VOS_ASSERT(0);
4681 }
4682 }
4683 }
4684 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4685 {
4686 ret = wait_for_completion_interruptible_timeout(
4687 &pAdapter->disconnect_comp_var,
4688 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4689 if (0 == ret)
4690 {
4691 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004692 }
4693 }
4694
4695 if (HDD_WMM_USER_MODE_NO_QOS ==
4696 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4697 {
4698 /*QoS not enabled in cfg file*/
4699 pRoamProfile->uapsd_mask = 0;
4700 }
4701 else
4702 {
4703 /*QoS enabled, update uapsd mask from cfg file*/
4704 pRoamProfile->uapsd_mask =
4705 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4706 }
4707
4708 pRoamProfile->SSIDs.numOfSSIDs = 1;
4709 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4710 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
4711 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
4712 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4713 ssid, ssid_len);
4714
4715 if (bssid)
4716 {
4717 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4718 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4719 WNI_CFG_BSSID_LEN);
4720 /* Save BSSID in seperate variable as well, as RoamProfile
4721 BSSID is getting zeroed out in the association process. And in
4722 case of join failure we should send valid BSSID to supplicant
4723 */
4724 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4725 WNI_CFG_BSSID_LEN);
4726 }
4727
4728 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4729 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4730 {
4731 /*set gen ie*/
4732 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4733 /*set auth*/
4734 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4735 }
4736 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4737 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4738 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4739 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4740 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4741 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4742 )
4743 {
4744 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4745 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4746 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4747 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4748 eCSR_AUTH_TYPE_AUTOSWITCH;
4749 pWextState->roamProfile.AuthType.authType[0] =
4750 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4751 }
4752#ifdef FEATURE_WLAN_WAPI
4753 if (pAdapter->wapi_info.nWapiMode)
4754 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004755 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004756 switch (pAdapter->wapi_info.wapiAuthMode)
4757 {
4758 case WAPI_AUTH_MODE_PSK:
4759 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004760 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004761 pAdapter->wapi_info.wapiAuthMode);
4762 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4763 break;
4764 }
4765 case WAPI_AUTH_MODE_CERT:
4766 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004767 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004768 pAdapter->wapi_info.wapiAuthMode);
4769 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4770 break;
4771 }
4772 } // End of switch
4773 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4774 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4775 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004776 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004777 pRoamProfile->AuthType.numEntries = 1;
4778 pRoamProfile->EncryptionType.numEntries = 1;
4779 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4780 pRoamProfile->mcEncryptionType.numEntries = 1;
4781 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4782 }
4783 }
4784#endif /* FEATURE_WLAN_WAPI */
4785 pRoamProfile->csrPersona = pAdapter->device_mode;
4786
Jeff Johnson32d95a32012-09-10 13:15:23 -07004787 if( operatingChannel )
4788 {
4789 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4790 pRoamProfile->ChannelInfo.numOfChannels = 1;
4791 }
4792
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004793 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
4794 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
4795 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
4796 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004797 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
4798 */
4799 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4800 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
4801 eConnectionState_Connecting);
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004802
Jeff Johnson295189b2012-06-20 16:38:30 -07004803 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4804 pAdapter->sessionId, pRoamProfile, &roamId);
4805
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004806 if( (eHAL_STATUS_SUCCESS != status) &&
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304807 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
4808
4809 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004810 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
4811 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
4812 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304813 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004814 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304815 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004816
4817 pRoamProfile->ChannelInfo.ChannelList = NULL;
4818 pRoamProfile->ChannelInfo.numOfChannels = 0;
4819
Jeff Johnson295189b2012-06-20 16:38:30 -07004820 }
4821 else
4822 {
4823 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4824 return -EINVAL;
4825 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004826 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004827 return status;
4828}
4829
4830/*
4831 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4832 * This function is used to set the authentication type (OPEN/SHARED).
4833 *
4834 */
4835static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4836 enum nl80211_auth_type auth_type)
4837{
4838 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4839 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4840
4841 ENTER();
4842
4843 /*set authentication type*/
4844 switch (auth_type)
4845 {
4846 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4847 case NL80211_AUTHTYPE_AUTOMATIC:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07004848#ifdef WLAN_FEATURE_VOWIFI_11R
4849 case NL80211_AUTHTYPE_FT:
4850#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07004851 hddLog(VOS_TRACE_LEVEL_INFO,
4852 "%s: set authentication type to OPEN", __func__);
4853 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4854 break;
4855
4856 case NL80211_AUTHTYPE_SHARED_KEY:
4857 hddLog(VOS_TRACE_LEVEL_INFO,
4858 "%s: set authentication type to SHARED", __func__);
4859 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4860 break;
4861#ifdef FEATURE_WLAN_CCX
4862 case NL80211_AUTHTYPE_NETWORK_EAP:
4863 hddLog(VOS_TRACE_LEVEL_INFO,
4864 "%s: set authentication type to CCKM WPA", __func__);
4865 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4866 break;
4867#endif
4868
4869
4870 default:
4871 hddLog(VOS_TRACE_LEVEL_ERROR,
4872 "%s: Unsupported authentication type %d", __func__,
4873 auth_type);
4874 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4875 return -EINVAL;
4876 }
4877
4878 pWextState->roamProfile.AuthType.authType[0] =
4879 pHddStaCtx->conn_info.authType;
4880 return 0;
4881}
4882
4883/*
4884 * FUNCTION: wlan_hdd_set_akm_suite
4885 * This function is used to set the key mgmt type(PSK/8021x).
4886 *
4887 */
4888static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
4889 u32 key_mgmt
4890 )
4891{
4892 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4893 ENTER();
4894
4895 /*set key mgmt type*/
4896 switch(key_mgmt)
4897 {
4898 case WLAN_AKM_SUITE_PSK:
4899 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
4900 __func__);
4901 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
4902 break;
4903
4904 case WLAN_AKM_SUITE_8021X:
4905 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
4906 __func__);
4907 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
4908 break;
4909#ifdef FEATURE_WLAN_CCX
4910#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
4911#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
4912 case WLAN_AKM_SUITE_CCKM:
4913 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
4914 __func__);
4915 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
4916 break;
4917#endif
4918
4919 default:
4920 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
4921 __func__, key_mgmt);
4922 return -EINVAL;
4923
4924 }
4925 return 0;
4926}
4927
4928/*
4929 * FUNCTION: wlan_hdd_cfg80211_set_cipher
4930 * This function is used to set the encryption type
4931 * (NONE/WEP40/WEP104/TKIP/CCMP).
4932 */
4933static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
4934 u32 cipher,
4935 bool ucast
4936 )
4937{
4938 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4939 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4940 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4941
4942 ENTER();
4943
4944 if (!cipher)
4945 {
4946 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
4947 __func__, cipher);
4948 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4949 }
4950 else
4951 {
4952
4953 /*set encryption method*/
4954 switch (cipher)
4955 {
4956 case IW_AUTH_CIPHER_NONE:
4957 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4958 break;
4959
4960 case WLAN_CIPHER_SUITE_WEP40:
4961 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4962 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4963 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
4964 else
4965 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4966 break;
4967
4968 case WLAN_CIPHER_SUITE_WEP104:
4969 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4970 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4971 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
4972 else
4973 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
4974 break;
4975
4976 case WLAN_CIPHER_SUITE_TKIP:
4977 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
4978 break;
4979
4980 case WLAN_CIPHER_SUITE_CCMP:
4981 encryptionType = eCSR_ENCRYPT_TYPE_AES;
4982 break;
4983#ifdef FEATURE_WLAN_WAPI
4984 case WLAN_CIPHER_SUITE_SMS4:
4985 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
4986 break;
4987#endif
4988
4989#ifdef FEATURE_WLAN_CCX
4990 case WLAN_CIPHER_SUITE_KRK:
4991 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
4992 break;
4993#endif
4994 default:
4995 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
4996 __func__, cipher);
4997 return -EOPNOTSUPP;
4998 }
4999 }
5000
5001 if (ucast)
5002 {
5003 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
5004 __func__, encryptionType);
5005 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5006 pWextState->roamProfile.EncryptionType.numEntries = 1;
5007 pWextState->roamProfile.EncryptionType.encryptionType[0] =
5008 encryptionType;
5009 }
5010 else
5011 {
5012 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
5013 __func__, encryptionType);
5014 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
5015 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
5016 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
5017 }
5018
5019 return 0;
5020}
5021
5022
5023/*
5024 * FUNCTION: wlan_hdd_cfg80211_set_ie
5025 * This function is used to parse WPA/RSN IE's.
5026 */
5027int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
5028 u8 *ie,
5029 size_t ie_len
5030 )
5031{
5032 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5033 u8 *genie = ie;
5034 v_U16_t remLen = ie_len;
5035#ifdef FEATURE_WLAN_WAPI
5036 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
5037 u16 *tmp;
5038 v_U16_t akmsuiteCount;
5039 int *akmlist;
5040#endif
5041 ENTER();
5042
5043 /* clear previous assocAddIE */
5044 pWextState->assocAddIE.length = 0;
5045 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
5046
5047 while (remLen >= 2)
5048 {
5049 v_U16_t eLen = 0;
5050 v_U8_t elementId;
5051 elementId = *genie++;
5052 eLen = *genie++;
5053 remLen -= 2;
5054
5055 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
5056 __func__, elementId, eLen);
5057
5058 switch ( elementId )
5059 {
5060 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005061 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 -07005062 {
5063 hddLog(VOS_TRACE_LEVEL_ERROR,
5064 "%s: Invalid WPA IE", __func__);
5065 return -EINVAL;
5066 }
5067 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
5068 {
5069 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5070 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
5071 __func__, eLen + 2);
5072
5073 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5074 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005075 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
5076 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005077 VOS_ASSERT(0);
5078 return -ENOMEM;
5079 }
5080 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5081 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5082 pWextState->assocAddIE.length += eLen + 2;
5083
5084 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
5085 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5086 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5087 }
5088 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
5089 {
5090 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
5091 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5092 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
5093 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
5094 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
5095 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005096 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
5097 P2P_OUI_TYPE_SIZE))
5098 /*Consider P2P IE, only for P2P Client */
5099 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5100 {
5101 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5102 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
5103 __func__, eLen + 2);
5104
5105 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5106 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005107 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5108 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005109 VOS_ASSERT(0);
5110 return -ENOMEM;
5111 }
5112 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5113 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5114 pWextState->assocAddIE.length += eLen + 2;
5115
5116 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5117 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5118 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005119#ifdef WLAN_FEATURE_WFD
5120 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
5121 WFD_OUI_TYPE_SIZE))
5122 /*Consider WFD IE, only for P2P Client */
5123 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5124 {
5125 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5126 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
5127 __func__, eLen + 2);
5128
5129 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5130 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005131 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5132 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005133 VOS_ASSERT(0);
5134 return -ENOMEM;
5135 }
5136 // WFD IE is saved to Additional IE ; it should be accumulated to handle
5137 // WPS IE + P2P IE + WFD IE
5138 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5139 pWextState->assocAddIE.length += eLen + 2;
5140
5141 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5142 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5143 }
5144#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005145 /* Appending HS 2.0 Indication Element in Assiciation Request */
5146 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005147 HS20_OUI_TYPE_SIZE)) )
5148 {
5149 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5150 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
5151 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005152
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005153 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5154 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005155 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5156 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005157 VOS_ASSERT(0);
5158 return -ENOMEM;
5159 }
5160 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5161 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005162
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005163 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5164 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5165 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005166
Jeff Johnson295189b2012-06-20 16:38:30 -07005167 break;
5168 case DOT11F_EID_RSN:
5169 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
5170 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5171 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
5172 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
5173 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
5174 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005175 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
5176 case DOT11F_EID_EXTCAP:
5177 {
5178 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5179 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
5180 __func__, eLen + 2);
5181
5182 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5183 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005184 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5185 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005186 VOS_ASSERT(0);
5187 return -ENOMEM;
5188 }
5189 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5190 pWextState->assocAddIE.length += eLen + 2;
5191
5192 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5193 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5194 break;
5195 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005196#ifdef FEATURE_WLAN_WAPI
5197 case WLAN_EID_WAPI:
5198 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
5199 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
5200 pAdapter->wapi_info.nWapiMode);
5201 tmp = (u16 *)ie;
5202 tmp = tmp + 2; // Skip element Id and Len, Version
5203 akmsuiteCount = WPA_GET_LE16(tmp);
5204 tmp = tmp + 1;
5205 akmlist = (int *)(tmp);
5206 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
5207 {
5208 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
5209 }
5210 else
5211 {
5212 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
5213 VOS_ASSERT(0);
5214 return -EINVAL;
5215 }
5216
5217 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
5218 {
5219 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005220 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005221 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
5222 }
5223 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
5224 {
5225 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005226 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005227 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
5228 }
5229 break;
5230#endif
5231 default:
5232 hddLog (VOS_TRACE_LEVEL_ERROR,
5233 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005234 /* when Unknown IE is received we should break and continue
5235 * to the next IE in the buffer instead we were returning
5236 * so changing this to break */
5237 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005238 }
5239 genie += eLen;
5240 remLen -= eLen;
5241 }
5242 EXIT();
5243 return 0;
5244}
5245
5246/*
5247 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5248 * This function is used to initialize the security
5249 * parameters during connect operation.
5250 */
5251int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
5252 struct cfg80211_connect_params *req
5253 )
5254{
5255 int status = 0;
5256 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5257 ENTER();
5258
5259 /*set wpa version*/
5260 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5261
5262 if (req->crypto.wpa_versions)
5263 {
5264 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
5265 && ( (req->ie_len)
5266 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
5267 // Make sure that it is including a WPA IE.
5268 /* Currently NL is putting WPA version 1 even for open,
5269 * since p2p ie is also put in same buffer.
5270 * */
5271 {
5272 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5273 }
5274 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
5275 {
5276 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5277 }
5278 }
5279
5280 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
5281 pWextState->wpaVersion);
5282
5283 /*set authentication type*/
5284 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
5285
5286 if (0 > status)
5287 {
5288 hddLog(VOS_TRACE_LEVEL_ERROR,
5289 "%s: failed to set authentication type ", __func__);
5290 return status;
5291 }
5292
5293 /*set key mgmt type*/
5294 if (req->crypto.n_akm_suites)
5295 {
5296 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
5297 if (0 > status)
5298 {
5299 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
5300 __func__);
5301 return status;
5302 }
5303 }
5304
5305 /*set pairwise cipher type*/
5306 if (req->crypto.n_ciphers_pairwise)
5307 {
5308 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
5309 req->crypto.ciphers_pairwise[0], true);
5310 if (0 > status)
5311 {
5312 hddLog(VOS_TRACE_LEVEL_ERROR,
5313 "%s: failed to set unicast cipher type", __func__);
5314 return status;
5315 }
5316 }
5317 else
5318 {
5319 /*Reset previous cipher suite to none*/
5320 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
5321 if (0 > status)
5322 {
5323 hddLog(VOS_TRACE_LEVEL_ERROR,
5324 "%s: failed to set unicast cipher type", __func__);
5325 return status;
5326 }
5327 }
5328
5329 /*set group cipher type*/
5330 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
5331 false);
5332
5333 if (0 > status)
5334 {
5335 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
5336 __func__);
5337 return status;
5338 }
5339
5340 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
5341 if (req->ie_len)
5342 {
5343 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
5344 if ( 0 > status)
5345 {
5346 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
5347 __func__);
5348 return status;
5349 }
5350 }
5351
5352 /*incase of WEP set default key information*/
5353 if (req->key && req->key_len)
5354 {
5355 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
5356 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
5357 )
5358 {
5359 if ( IW_AUTH_KEY_MGMT_802_1X
5360 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
5361 {
5362 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
5363 __func__);
5364 return -EOPNOTSUPP;
5365 }
5366 else
5367 {
5368 u8 key_len = req->key_len;
5369 u8 key_idx = req->key_idx;
5370
5371 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
5372 && (CSR_MAX_NUM_KEY > key_idx)
5373 )
5374 {
5375 hddLog(VOS_TRACE_LEVEL_INFO,
5376 "%s: setting default wep key, key_idx = %hu key_len %hu",
5377 __func__, key_idx, key_len);
5378 vos_mem_copy(
5379 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
5380 req->key, key_len);
5381 pWextState->roamProfile.Keys.KeyLength[key_idx] =
5382 (u8)key_len;
5383 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
5384 }
5385 }
5386 }
5387 }
5388
5389 return status;
5390}
5391
5392/*
5393 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5394 * This function is used to initialize the security
5395 * parameters during connect operation.
5396 */
5397static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
5398 struct net_device *ndev,
5399 struct cfg80211_connect_params *req
5400 )
5401{
5402 int status = 0;
5403 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
5404 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
5405 hdd_context_t *pHddCtx = NULL;
5406
5407 ENTER();
5408
5409 hddLog(VOS_TRACE_LEVEL_INFO,
5410 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5411
5412 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5413 {
5414 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5415 "%s:LOGP in Progress. Ignore!!!", __func__);
5416 return -EAGAIN;
5417 }
5418
5419#ifdef WLAN_BTAMP_FEATURE
5420 //Infra connect not supported when AMP traffic is on.
5421 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
5422 {
5423 hddLog(VOS_TRACE_LEVEL_ERROR,
5424 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005425 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07005426 }
5427#endif
5428 /*initialise security parameters*/
5429 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
5430
5431 if ( 0 > status)
5432 {
5433 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
5434 __func__);
5435 return status;
5436 }
5437
5438 //If Device Mode is Station Concurrent Sessions Exit BMps
Jeff Johnsona8a1a482012-12-12 16:49:33 -08005439 //P2P Mode will be taken care in Open/close adapter
Jeff Johnson295189b2012-06-20 16:38:30 -07005440 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
5441 (vos_concurrent_sessions_running()))
5442 {
5443 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5444
5445 if (NULL != pVosContext)
5446 {
5447 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5448 if(NULL != pHddCtx)
5449 {
5450 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
5451 }
5452 }
5453 }
5454
Mohit Khanna765234a2012-09-11 15:08:35 -07005455 if ( req->channel )
5456 {
5457 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5458 req->ssid_len, req->bssid,
5459 req->channel->hw_value);
5460 }
5461 else
5462 {
5463 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5464 req->ssid_len, req->bssid,
5465 0);
5466 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005467
5468 if (0 > status)
5469 {
5470 //ReEnable BMPS if disabled
5471 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5472 (NULL != pHddCtx))
5473 {
5474 //ReEnable Bmps and Imps back
5475 hdd_enable_bmps_imps(pHddCtx);
5476 }
5477
5478 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5479 return status;
5480 }
5481 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
5482 EXIT();
5483 return status;
5484}
5485
5486
5487/*
5488 * FUNCTION: wlan_hdd_cfg80211_disconnect
5489 * This function is used to issue a disconnect request to SME
5490 */
5491static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
5492 struct net_device *dev,
5493 u16 reason
5494 )
5495{
5496 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5497 tCsrRoamProfile *pRoamProfile =
5498 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
5499 int status = 0;
5500 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005501#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005502 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005503 tANI_U8 staIdx;
5504#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005505
5506 ENTER();
5507
5508 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
5509 __func__,pAdapter->device_mode);
5510
5511 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5512 __func__, reason);
5513
5514 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
5515 {
5516 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5517 "%s:LOGP in Progress. Ignore!!!",__func__);
5518 return -EAGAIN;
5519 }
5520 if (NULL != pRoamProfile)
5521 {
5522 /*issue disconnect request to SME, if station is in connected state*/
5523 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
5524 {
5525 eCsrRoamDisconnectReason reasonCode =
5526 eCSR_DISCONNECT_REASON_UNSPECIFIED;
5527 switch(reason)
5528 {
5529 case WLAN_REASON_MIC_FAILURE:
5530 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
5531 break;
5532
5533 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
5534 case WLAN_REASON_DISASSOC_AP_BUSY:
5535 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
5536 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
5537 break;
5538
5539 case WLAN_REASON_PREV_AUTH_NOT_VALID:
5540 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
5541 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
5542 break;
5543
5544 case WLAN_REASON_DEAUTH_LEAVING:
5545 default:
5546 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
5547 break;
5548 }
5549 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5550 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
5551 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5552
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005553#ifdef FEATURE_WLAN_TDLS
5554 /* First clean up the tdls peers if any */
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005555 for (staIdx = 0 ; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005556 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005557 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId == pAdapter->sessionId) &&
5558 (pHddCtx->tdlsConnInfo[staIdx].staId))
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005559 {
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005560 uint8 *mac;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005561 mac = pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005562 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07005563 "%s: call sme_DeleteTdlsPeerSta staId %d sessionId %d " MAC_ADDRESS_STR,
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005564 __func__, pHddCtx->tdlsConnInfo[staIdx].staId, pAdapter->sessionId,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07005565 MAC_ADDR_ARRAY(mac));
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005566 sme_DeleteTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005567 pAdapter->sessionId,
5568 mac);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005569 }
5570 }
5571#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005572 /*issue disconnect*/
5573 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5574 pAdapter->sessionId, reasonCode);
5575
5576 if ( 0 != status)
5577 {
5578 hddLog(VOS_TRACE_LEVEL_ERROR,
5579 "%s csrRoamDisconnect failure, returned %d \n",
5580 __func__, (int)status );
5581 return -EINVAL;
5582 }
5583
5584 wait_for_completion_interruptible_timeout(
5585 &pAdapter->disconnect_comp_var,
5586 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5587
5588
5589 /*stop tx queues*/
5590 netif_tx_disable(dev);
5591 netif_carrier_off(dev);
5592 }
5593 }
5594 else
5595 {
5596 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
5597 }
5598
5599 return status;
5600}
5601
5602/*
5603 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
5604 * This function is used to initialize the security
5605 * settings in IBSS mode.
5606 */
5607static int wlan_hdd_cfg80211_set_privacy_ibss(
5608 hdd_adapter_t *pAdapter,
5609 struct cfg80211_ibss_params *params
5610 )
5611{
5612 int status = 0;
5613 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5614 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5615 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5616
5617 ENTER();
5618
5619 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5620
5621 if (params->ie_len && ( NULL != params->ie) )
5622 {
5623 if (WLAN_EID_RSN == params->ie[0])
5624 {
5625 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5626 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5627 }
5628 else
5629 {
5630 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5631 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5632 }
5633 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
5634
5635 if (0 > status)
5636 {
5637 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
5638 __func__);
5639 return status;
5640 }
5641 }
5642
5643 pWextState->roamProfile.AuthType.authType[0] =
5644 pHddStaCtx->conn_info.authType =
5645 eCSR_AUTH_TYPE_OPEN_SYSTEM;
5646
5647 if (params->privacy)
5648 {
5649 /* Security enabled IBSS, At this time there is no information available
5650 * about the security paramters, so initialise the encryption type to
5651 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
5652 * The correct security parameters will be updated later in
5653 * wlan_hdd_cfg80211_add_key */
5654 /* Hal expects encryption type to be set inorder
5655 *enable privacy bit in beacons */
5656
5657 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5658 }
5659
5660 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5661 pWextState->roamProfile.EncryptionType.numEntries = 1;
5662 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
5663
5664 return status;
5665}
5666
5667/*
5668 * FUNCTION: wlan_hdd_cfg80211_join_ibss
5669 * This function is used to create/join an IBSS
5670 */
5671static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
5672 struct net_device *dev,
5673 struct cfg80211_ibss_params *params
5674 )
5675{
5676 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5677 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5678 tCsrRoamProfile *pRoamProfile;
5679 int status;
5680 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5681
5682 ENTER();
5683
5684 hddLog(VOS_TRACE_LEVEL_INFO,
5685 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5686
5687 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5688 {
5689 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5690 "%s:LOGP in Progress. Ignore!!!", __func__);
5691 return -EAGAIN;
5692 }
5693
5694 if (NULL == pWextState)
5695 {
5696 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5697 __func__);
5698 return -EIO;
5699 }
5700
5701 pRoamProfile = &pWextState->roamProfile;
5702
5703 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
5704 {
5705 hddLog (VOS_TRACE_LEVEL_ERROR,
5706 "%s Interface type is not set to IBSS \n", __func__);
5707 return -EINVAL;
5708 }
5709
5710 /* Set Channel */
5711 if (NULL != params->channel)
5712 {
5713 u8 channelNum;
5714 if (IEEE80211_BAND_5GHZ == params->channel->band)
5715 {
5716 hddLog(VOS_TRACE_LEVEL_ERROR,
5717 "%s: IBSS join is called with unsupported band %d",
5718 __func__, params->channel->band);
5719 return -EOPNOTSUPP;
5720 }
5721
5722 /* Get channel number */
5723 channelNum =
5724 ieee80211_frequency_to_channel(params->channel->center_freq);
5725
5726 /*TODO: use macro*/
5727 if (14 >= channelNum)
5728 {
5729 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5730 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5731 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5732 int indx;
5733
5734 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5735 validChan, &numChans))
5736 {
5737 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
5738 __func__);
5739 return -EOPNOTSUPP;
5740 }
5741
5742 for (indx = 0; indx < numChans; indx++)
5743 {
5744 if (channelNum == validChan[indx])
5745 {
5746 break;
5747 }
5748 }
5749 if (indx >= numChans)
5750 {
5751 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
5752 __func__, channelNum);
5753 return -EINVAL;
5754 }
5755 /* Set the Operational Channel */
5756 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
5757 channelNum);
5758 pRoamProfile->ChannelInfo.numOfChannels = 1;
5759 pHddStaCtx->conn_info.operationChannel = channelNum;
5760 pRoamProfile->ChannelInfo.ChannelList =
5761 &pHddStaCtx->conn_info.operationChannel;
5762 }
5763 else
5764 {
5765 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5766 __func__, channelNum);
5767 return -EINVAL;
5768 }
5769 }
5770
5771 /* Initialize security parameters */
5772 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5773 if (status < 0)
5774 {
5775 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5776 __func__);
5777 return status;
5778 }
5779
5780 /* Issue connect start */
5781 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005782 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005783
5784 if (0 > status)
5785 {
5786 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5787 return status;
5788 }
5789
5790 return 0;
5791}
5792
5793/*
5794 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5795 * This function is used to leave an IBSS
5796 */
5797static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5798 struct net_device *dev
5799 )
5800{
5801 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5802 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5803 tCsrRoamProfile *pRoamProfile;
5804
5805 ENTER();
5806
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005807 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5808 {
5809 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5810 "%s:LOGP in Progress. Ignore!!!", __func__);
5811 return -EAGAIN;
5812 }
5813
Jeff Johnson295189b2012-06-20 16:38:30 -07005814 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5815 if (NULL == pWextState)
5816 {
5817 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5818 __func__);
5819 return -EIO;
5820 }
5821
5822 pRoamProfile = &pWextState->roamProfile;
5823
5824 /* Issue disconnect only if interface type is set to IBSS */
5825 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5826 {
5827 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5828 __func__);
5829 return -EINVAL;
5830 }
5831
5832 /* Issue Disconnect request */
5833 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5834 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5835 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5836
5837 return 0;
5838}
5839
5840/*
5841 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5842 * This function is used to set the phy parameters
5843 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5844 */
5845static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5846 u32 changed)
5847{
5848 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5849 tHalHandle hHal = pHddCtx->hHal;
5850
5851 ENTER();
5852
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005853 if ( pHddCtx->isLogpInProgress )
5854 {
5855 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5856 "%s:LOGP in Progress. Ignore!!!", __func__);
5857 return -EAGAIN;
5858 }
5859
Jeff Johnson295189b2012-06-20 16:38:30 -07005860 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
5861 {
5862 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
5863 WNI_CFG_RTS_THRESHOLD_STAMAX :
5864 wiphy->rts_threshold;
5865
5866 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
5867 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
5868 {
5869 hddLog(VOS_TRACE_LEVEL_ERROR,
5870 "%s: Invalid RTS Threshold value %hu",
5871 __func__, rts_threshold);
5872 return -EINVAL;
5873 }
5874
5875 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
5876 rts_threshold, ccmCfgSetCallback,
5877 eANI_BOOLEAN_TRUE))
5878 {
5879 hddLog(VOS_TRACE_LEVEL_ERROR,
5880 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
5881 __func__, rts_threshold);
5882 return -EIO;
5883 }
5884
5885 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
5886 rts_threshold);
5887 }
5888
5889 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
5890 {
5891 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
5892 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
5893 wiphy->frag_threshold;
5894
5895 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
5896 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
5897 {
5898 hddLog(VOS_TRACE_LEVEL_ERROR,
5899 "%s: Invalid frag_threshold value %hu", __func__,
5900 frag_threshold);
5901 return -EINVAL;
5902 }
5903
5904 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
5905 frag_threshold, ccmCfgSetCallback,
5906 eANI_BOOLEAN_TRUE))
5907 {
5908 hddLog(VOS_TRACE_LEVEL_ERROR,
5909 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
5910 __func__, frag_threshold);
5911 return -EIO;
5912 }
5913
5914 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
5915 frag_threshold);
5916 }
5917
5918 if ((changed & WIPHY_PARAM_RETRY_SHORT)
5919 || (changed & WIPHY_PARAM_RETRY_LONG))
5920 {
5921 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
5922 wiphy->retry_short :
5923 wiphy->retry_long;
5924
5925 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
5926 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
5927 {
5928 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
5929 __func__, retry_value);
5930 return -EINVAL;
5931 }
5932
5933 if (changed & WIPHY_PARAM_RETRY_SHORT)
5934 {
5935 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
5936 retry_value, ccmCfgSetCallback,
5937 eANI_BOOLEAN_TRUE))
5938 {
5939 hddLog(VOS_TRACE_LEVEL_ERROR,
5940 "%s: ccmCfgSetInt failed for long retry count %hu",
5941 __func__, retry_value);
5942 return -EIO;
5943 }
5944 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
5945 __func__, retry_value);
5946 }
5947 else if (changed & WIPHY_PARAM_RETRY_SHORT)
5948 {
5949 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
5950 retry_value, ccmCfgSetCallback,
5951 eANI_BOOLEAN_TRUE))
5952 {
5953 hddLog(VOS_TRACE_LEVEL_ERROR,
5954 "%s: ccmCfgSetInt failed for short retry count %hu",
5955 __func__, retry_value);
5956 return -EIO;
5957 }
5958 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
5959 __func__, retry_value);
5960 }
5961 }
5962
5963 return 0;
5964}
5965
5966/*
5967 * FUNCTION: wlan_hdd_cfg80211_set_txpower
5968 * This function is used to set the txpower
5969 */
5970static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
5971#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
5972 enum tx_power_setting type,
5973#else
5974 enum nl80211_tx_power_setting type,
5975#endif
5976 int dbm)
5977{
5978 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5979 tHalHandle hHal = pHddCtx->hHal;
5980 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5981 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5982
5983 ENTER();
5984
5985 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
5986 dbm, ccmCfgSetCallback,
5987 eANI_BOOLEAN_TRUE))
5988 {
5989 hddLog(VOS_TRACE_LEVEL_ERROR,
5990 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
5991 return -EIO;
5992 }
5993
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005994 if ( pHddCtx->isLogpInProgress )
5995 {
5996 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5997 "%s:LOGP in Progress. Ignore!!!", __func__);
5998 return -EAGAIN;
5999 }
6000
Jeff Johnson295189b2012-06-20 16:38:30 -07006001 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
6002 dbm);
6003
6004 switch(type)
6005 {
6006 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
6007 /* Fall through */
6008 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
6009 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
6010 {
6011 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
6012 __func__);
6013 return -EIO;
6014 }
6015 break;
6016 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
6017 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
6018 __func__);
6019 return -EOPNOTSUPP;
6020 break;
6021 default:
6022 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
6023 __func__, type);
6024 return -EIO;
6025 }
6026
6027 return 0;
6028}
6029
6030/*
6031 * FUNCTION: wlan_hdd_cfg80211_get_txpower
6032 * This function is used to read the txpower
6033 */
6034static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
6035{
6036
6037 hdd_adapter_t *pAdapter;
6038 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6039
Jeff Johnsone7245742012-09-05 17:12:55 -07006040 ENTER();
6041
Jeff Johnson295189b2012-06-20 16:38:30 -07006042 if (NULL == pHddCtx)
6043 {
6044 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
6045 *dbm = 0;
6046 return -ENOENT;
6047 }
6048
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006049 if ( pHddCtx->isLogpInProgress )
6050 {
6051 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6052 "%s:LOGP in Progress. Ignore!!!", __func__);
6053 return -EAGAIN;
6054 }
6055
Jeff Johnson295189b2012-06-20 16:38:30 -07006056 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
6057 if (NULL == pAdapter)
6058 {
6059 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
6060 return -ENOENT;
6061 }
6062
6063 wlan_hdd_get_classAstats(pAdapter);
6064 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
6065
Jeff Johnsone7245742012-09-05 17:12:55 -07006066 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006067 return 0;
6068}
6069
6070static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
6071 u8* mac, struct station_info *sinfo)
6072{
6073 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
6074 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6075 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
6076 tANI_U8 rate_flags;
6077
6078 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6079 hdd_config_t *pCfg = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07006080
6081 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
6082 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
6083 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
6084 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
6085 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
6086 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
6087 tANI_U16 maxRate = 0;
6088 tANI_U16 myRate;
6089 tANI_U16 currentRate = 0;
6090 tANI_U8 maxSpeedMCS = 0;
6091 tANI_U8 maxMCSIdx = 0;
6092 tANI_U8 rateFlag = 1;
6093 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006094 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07006095
Jeff Johnsone7245742012-09-05 17:12:55 -07006096 ENTER();
6097
Jeff Johnson295189b2012-06-20 16:38:30 -07006098 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
6099 (0 == ssidlen))
6100 {
6101 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
6102 " Invalid ssidlen, %d", __func__, ssidlen);
6103 /*To keep GUI happy*/
6104 return 0;
6105 }
6106
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006107 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6108 {
6109 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6110 "%s:LOGP in Progress. Ignore!!!", __func__);
6111 return -EAGAIN;
6112 }
6113
Jeff Johnson295189b2012-06-20 16:38:30 -07006114 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
6115 sinfo->filled |= STATION_INFO_SIGNAL;
6116
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006117 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006118 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
6119
6120 //convert to the UI units of 100kbps
6121 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
6122
6123#ifdef LINKSPEED_DEBUG_ENABLED
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006124 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 -07006125 sinfo->signal,
6126 pCfg->reportMaxLinkSpeed,
6127 myRate,
6128 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006129 (int) pCfg->linkSpeedRssiMid,
6130 (int) pCfg->linkSpeedRssiLow,
6131 (int) rate_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07006132#endif //LINKSPEED_DEBUG_ENABLED
6133
6134 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
6135 {
6136 // we do not want to necessarily report the current speed
6137 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
6138 {
6139 // report the max possible speed
6140 rssidx = 0;
6141 }
6142 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
6143 {
6144 // report the max possible speed with RSSI scaling
6145 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
6146 {
6147 // report the max possible speed
6148 rssidx = 0;
6149 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006150 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07006151 {
6152 // report middle speed
6153 rssidx = 1;
6154 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006155 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
6156 {
6157 // report middle speed
6158 rssidx = 2;
6159 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006160 else
6161 {
6162 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006163 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07006164 }
6165 }
6166 else
6167 {
6168 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
6169 hddLog(VOS_TRACE_LEVEL_ERROR,
6170 "%s: Invalid value for reportMaxLinkSpeed: %u",
6171 __func__, pCfg->reportMaxLinkSpeed);
6172 rssidx = 0;
6173 }
6174
6175 maxRate = 0;
6176
6177 /* Get Basic Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306178 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_OPERATIONAL_RATE_SET,
6179 OperationalRates, &ORLeng))
6180 {
6181 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6182 /*To keep GUI happy*/
6183 return 0;
6184 }
6185
Jeff Johnson295189b2012-06-20 16:38:30 -07006186 for (i = 0; i < ORLeng; i++)
6187 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006188 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006189 {
6190 /* Validate Rate Set */
6191 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
6192 {
6193 currentRate = supported_data_rate[j].supported_rate[rssidx];
6194 break;
6195 }
6196 }
6197 /* Update MAX rate */
6198 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6199 }
6200
6201 /* Get Extended Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306202 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
6203 ExtendedRates, &ERLeng))
6204 {
6205 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6206 /*To keep GUI happy*/
6207 return 0;
6208 }
6209
Jeff Johnson295189b2012-06-20 16:38:30 -07006210 for (i = 0; i < ERLeng; i++)
6211 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006212 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006213 {
6214 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
6215 {
6216 currentRate = supported_data_rate[j].supported_rate[rssidx];
6217 break;
6218 }
6219 }
6220 /* Update MAX rate */
6221 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6222 }
6223
6224 /* Get MCS Rate Set -- but only if we are connected at MCS
6225 rates or if we are always reporting max speed or if we have
6226 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006227 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07006228 {
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306229 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_CURRENT_MCS_SET,
6230 MCSRates, &MCSLeng))
6231 {
6232 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6233 /*To keep GUI happy*/
6234 return 0;
6235 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006236 rateFlag = 0;
6237 if (rate_flags & eHAL_TX_RATE_HT40)
6238 {
6239 rateFlag |= 1;
6240 }
6241 if (rate_flags & eHAL_TX_RATE_SGI)
6242 {
6243 rateFlag |= 2;
6244 }
6245
6246 for (i = 0; i < MCSLeng; i++)
6247 {
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006248 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
6249 for (j = 0; j < temp; j++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006250 {
6251 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
6252 {
6253 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
6254 break;
6255 }
6256 }
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006257 if ((j < temp) && (currentRate > maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006258 {
6259 maxRate = currentRate;
6260 maxSpeedMCS = 1;
6261 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
6262 }
6263 }
6264 }
6265
6266 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006267 if (((maxRate < myRate) && (0 == rssidx)) ||
6268 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006269 {
6270 maxRate = myRate;
6271 if (rate_flags & eHAL_TX_RATE_LEGACY)
6272 {
6273 maxSpeedMCS = 0;
6274 }
6275 else
6276 {
6277 maxSpeedMCS = 1;
6278 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6279 }
6280 }
6281
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006282 if ((!maxSpeedMCS) || (0 != rssidx))
Jeff Johnson295189b2012-06-20 16:38:30 -07006283 {
6284 sinfo->txrate.legacy = maxRate;
6285#ifdef LINKSPEED_DEBUG_ENABLED
6286 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
6287#endif //LINKSPEED_DEBUG_ENABLED
6288 }
6289 else
6290 {
6291 sinfo->txrate.mcs = maxMCSIdx;
6292 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6293 if (rate_flags & eHAL_TX_RATE_SGI)
6294 {
6295 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6296 }
6297 if (rate_flags & eHAL_TX_RATE_HT40)
6298 {
6299 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6300 }
6301#ifdef LINKSPEED_DEBUG_ENABLED
6302 pr_info("Reporting MCS rate %d flags %x\n",
6303 sinfo->txrate.mcs,
6304 sinfo->txrate.flags );
6305#endif //LINKSPEED_DEBUG_ENABLED
6306 }
6307 }
6308 else
6309 {
6310 // report current rate instead of max rate
6311
6312 if (rate_flags & eHAL_TX_RATE_LEGACY)
6313 {
6314 //provide to the UI in units of 100kbps
6315 sinfo->txrate.legacy = myRate;
6316#ifdef LINKSPEED_DEBUG_ENABLED
6317 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
6318#endif //LINKSPEED_DEBUG_ENABLED
6319 }
6320 else
6321 {
6322 //must be MCS
6323 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6324 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6325 if (rate_flags & eHAL_TX_RATE_SGI)
6326 {
6327 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6328 }
6329 if (rate_flags & eHAL_TX_RATE_HT40)
6330 {
6331 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6332 }
6333#ifdef LINKSPEED_DEBUG_ENABLED
6334 pr_info("Reporting actual MCS rate %d flags %x\n",
6335 sinfo->txrate.mcs,
6336 sinfo->txrate.flags );
6337#endif //LINKSPEED_DEBUG_ENABLED
6338 }
6339 }
6340 sinfo->filled |= STATION_INFO_TX_BITRATE;
6341
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006342 sinfo->tx_packets =
6343 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
6344 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
6345 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
6346 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
6347
6348 sinfo->tx_retries =
6349 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
6350 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
6351 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
6352 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
6353
6354 sinfo->tx_failed =
6355 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
6356 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
6357 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
6358 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
6359
6360 sinfo->filled |=
6361 STATION_INFO_TX_PACKETS |
6362 STATION_INFO_TX_RETRIES |
6363 STATION_INFO_TX_FAILED;
6364
6365 EXIT();
6366 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006367}
6368
6369static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
6370 struct net_device *dev, bool mode, v_SINT_t timeout)
6371{
6372 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6373 VOS_STATUS vos_status;
6374
Jeff Johnsone7245742012-09-05 17:12:55 -07006375 ENTER();
6376
Jeff Johnson295189b2012-06-20 16:38:30 -07006377 if (NULL == pAdapter)
6378 {
6379 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6380 return -ENODEV;
6381 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006382 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6383 {
6384 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6385 "%s:LOGP in Progress. Ignore!!!", __func__);
6386 return -EAGAIN;
6387 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006388
6389 /**The get power cmd from the supplicant gets updated by the nl only
6390 *on successful execution of the function call
6391 *we are oppositely mapped w.r.t mode in the driver
6392 **/
6393 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
6394
Jeff Johnsone7245742012-09-05 17:12:55 -07006395 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006396 if (VOS_STATUS_E_FAILURE == vos_status)
6397 {
6398 return -EINVAL;
6399 }
6400 return 0;
6401}
6402
6403
6404#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6405static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
6406 struct net_device *netdev,
6407 u8 key_index)
6408{
Jeff Johnsone7245742012-09-05 17:12:55 -07006409 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006410 return 0;
6411}
6412#endif //LINUX_VERSION_CODE
6413
6414#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
6415static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6416 struct net_device *dev,
6417 struct ieee80211_txq_params *params)
6418{
Jeff Johnsone7245742012-09-05 17:12:55 -07006419 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006420 return 0;
6421}
6422#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6423static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6424 struct ieee80211_txq_params *params)
6425{
Jeff Johnsone7245742012-09-05 17:12:55 -07006426 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006427 return 0;
6428}
6429#endif //LINUX_VERSION_CODE
6430
6431static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
6432 struct net_device *dev, u8 *mac)
6433{
6434 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006435 VOS_STATUS vos_status;
6436 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006437
Jeff Johnsone7245742012-09-05 17:12:55 -07006438 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006439 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6440 {
6441 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6442 return -EINVAL;
6443 }
6444
6445 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6446 {
6447 hddLog( LOGE,
6448 "%s: Wlan Load/Unload is in progress", __func__);
6449 return -EBUSY;
6450 }
6451
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006452 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6453 {
6454 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6455 "%s:LOGP in Progress. Ignore!!!", __func__);
6456 return -EAGAIN;
6457 }
6458
Jeff Johnson295189b2012-06-20 16:38:30 -07006459 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006460 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006461 )
6462 {
6463 if( NULL == mac )
6464 {
6465 v_U16_t i;
6466 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
6467 {
6468 if(pAdapter->aStaInfo[i].isUsed)
6469 {
6470 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
6471 hddLog(VOS_TRACE_LEVEL_INFO,
6472 "%s: Delete STA with MAC::"
6473 "%02x:%02x:%02x:%02x:%02x:%02x",
6474 __func__,
6475 macAddr[0], macAddr[1], macAddr[2],
6476 macAddr[3], macAddr[4], macAddr[5]);
6477 hdd_softap_sta_deauth(pAdapter, macAddr);
6478 }
6479 }
6480 }
6481 else
6482 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006483
6484 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
6485 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6486 {
6487 hddLog(VOS_TRACE_LEVEL_INFO,
6488 "%s: Skip this DEL STA as this is not used::"
6489 "%02x:%02x:%02x:%02x:%02x:%02x",
6490 __func__,
6491 mac[0], mac[1], mac[2],
6492 mac[3], mac[4], mac[5]);
6493 return -ENOENT;
6494 }
6495
6496 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
6497 {
6498 hddLog(VOS_TRACE_LEVEL_INFO,
6499 "%s: Skip this DEL STA as deauth is in progress::"
6500 "%02x:%02x:%02x:%02x:%02x:%02x",
6501 __func__,
6502 mac[0], mac[1], mac[2],
6503 mac[3], mac[4], mac[5]);
6504 return -ENOENT;
6505 }
6506
6507 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
6508
Jeff Johnson295189b2012-06-20 16:38:30 -07006509 hddLog(VOS_TRACE_LEVEL_INFO,
6510 "%s: Delete STA with MAC::"
6511 "%02x:%02x:%02x:%02x:%02x:%02x",
6512 __func__,
6513 mac[0], mac[1], mac[2],
6514 mac[3], mac[4], mac[5]);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006515
6516 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
6517 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6518 {
6519 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
6520 hddLog(VOS_TRACE_LEVEL_INFO,
6521 "%s: STA removal failed for ::"
6522 "%02x:%02x:%02x:%02x:%02x:%02x",
6523 __func__,
6524 mac[0], mac[1], mac[2],
6525 mac[3], mac[4], mac[5]);
6526 return -ENOENT;
6527 }
6528
Jeff Johnson295189b2012-06-20 16:38:30 -07006529 }
6530 }
6531
6532 EXIT();
6533
6534 return 0;
6535}
6536
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006537static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
6538 struct net_device *dev, u8 *mac, struct station_parameters *params)
6539{
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006540 int status = -EPERM;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006541#ifdef FEATURE_WLAN_TDLS
6542 u32 mask, set;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006543 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006544 mask = params->sta_flags_mask;
6545
6546 set = params->sta_flags_set;
6547
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006548#ifdef WLAN_FEATURE_TDLS_DEBUG
6549 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6550 "%s: mask 0x%x set 0x%x " MAC_ADDRESS_STR,
6551 __func__, mask, set, MAC_ADDR_ARRAY(mac));
6552#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006553
6554 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6555 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006556 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006557 }
6558 }
6559#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006560 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006561}
6562
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006563
6564#ifdef FEATURE_WLAN_LFR
6565static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006566 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006567{
6568#define MAX_PMKSAIDS_IN_CACHE 8
6569 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -07006570 static tANI_U32 i; // HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006571 tANI_U32 j=0;
6572 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6573 tHalHandle halHandle;
6574 eHalStatus result;
6575 tANI_U8 BSSIDMatched = 0;
6576
Jeff Johnsone7245742012-09-05 17:12:55 -07006577 ENTER();
6578
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006579 // Validate pAdapter
6580 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6581 {
6582 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6583 return -EINVAL;
6584 }
6585
6586 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6587 {
6588 hddLog( LOGE,
6589 "%s: Wlan Load/Unload is in progress", __func__);
6590 return -EBUSY;
6591 }
6592
6593 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6594 {
6595 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6596 "%s:LOGP in Progress. Ignore!!!", __func__);
6597 return -EAGAIN;
6598 }
6599
6600 // Retrieve halHandle
6601 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
6602
6603 for (j = 0; j < i; j++)
6604 {
6605 if(vos_mem_compare(PMKIDCache[j].BSSID,
6606 pmksa->bssid, WNI_CFG_BSSID_LEN))
6607 {
6608 /* BSSID matched previous entry. Overwrite it. */
6609 BSSIDMatched = 1;
6610 vos_mem_copy(PMKIDCache[j].BSSID,
6611 pmksa->bssid, WNI_CFG_BSSID_LEN);
6612 vos_mem_copy(PMKIDCache[j].PMKID,
6613 pmksa->pmkid,
6614 CSR_RSN_PMKID_SIZE);
6615 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006616 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006617 dump_bssid(pmksa->bssid);
6618 dump_pmkid(halHandle, pmksa->pmkid);
6619 break;
6620 }
6621 }
6622
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07006623 /* Check we compared all entries,if then take the first slot now */
6624 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
6625
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006626 if (!BSSIDMatched)
6627 {
6628 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
6629 vos_mem_copy(PMKIDCache[i].BSSID,
6630 pmksa->bssid, ETHER_ADDR_LEN);
6631 vos_mem_copy(PMKIDCache[i].PMKID,
6632 pmksa->pmkid,
6633 CSR_RSN_PMKID_SIZE);
6634 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006635 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006636 dump_bssid(pmksa->bssid);
6637 dump_pmkid(halHandle, pmksa->pmkid);
6638 // Increment the HDD Local Cache index
6639 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
6640 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
6641 }
6642
6643
6644 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
6645 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006646 // __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006647 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006648 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006649 // Finally set the PMKSA ID Cache in CSR
6650 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
6651 PMKIDCache,
6652 i );
6653 return 0;
6654}
6655
6656
6657static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006658 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006659{
Jeff Johnsone7245742012-09-05 17:12:55 -07006660 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006661 // TODO: Implement this later.
6662 return 0;
6663}
6664
6665static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
6666{
Jeff Johnsone7245742012-09-05 17:12:55 -07006667 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006668 // TODO: Implement this later.
6669 return 0;
6670}
6671#endif
6672
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006673#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6674static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
6675 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
6676{
6677 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6678 hdd_station_ctx_t *pHddStaCtx;
6679
6680 if (NULL == pAdapter)
6681 {
6682 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6683 return -ENODEV;
6684 }
6685
6686 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6687
6688 // Added for debug on reception of Re-assoc Req.
6689 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6690 {
6691 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
6692 ftie->ie_len);
6693 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
6694 }
6695
6696#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
6697 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
6698 ftie->ie_len);
6699#endif
6700
6701 // Pass the received FT IEs to SME
6702 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, ftie->ie,
6703 ftie->ie_len);
6704 return 0;
6705}
6706#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006707
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006708#ifdef FEATURE_WLAN_TDLS
6709static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
6710 u8 *peer, u8 action_code, u8 dialog_token,
6711 u16 status_code, const u8 *buf, size_t len)
6712{
6713
6714 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6715 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006716 u8 peerMac[6];
6717 VOS_STATUS status;
Gopichand Nakkala05922802013-03-14 12:23:19 -07006718 int max_sta_failed = 0;
Hoonki Leea34dd892013-02-05 22:56:02 -08006719 int responder;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006720
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006721 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006722 {
6723 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6724 "Invalid arguments");
6725 return -EINVAL;
6726 }
6727
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006728 if (pHddCtx->isLogpInProgress)
6729 {
6730 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6731 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006732 wlan_hdd_tdls_set_link_status(pAdapter, peer, eTDLS_LINK_IDLE);
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006733 return -EBUSY;
6734 }
6735
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006736 if (FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006737 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6738 {
6739 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6740 "TDLS Disabled in INI OR not enabled in FW.\
6741 Cannot process TDLS commands \n");
6742 return -ENOTSUPP;
6743 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006744
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006745 if (WLAN_IS_TDLS_SETUP_ACTION(action_code))
6746 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006747 if (wlan_hdd_tdls_is_progress(pAdapter, peer, TRUE))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006748 {
6749 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006750 "%s: " MAC_ADDRESS_STR
6751 " TDLS setup is ongoing. Request declined.",
6752 __func__, MAC_ADDR_ARRAY(peer));
Gopichand Nakkala05922802013-03-14 12:23:19 -07006753 goto error;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006754 }
6755 }
6756
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006757 if (SIR_MAC_TDLS_SETUP_REQ == action_code ||
6758 SIR_MAC_TDLS_SETUP_RSP == action_code )
Lee Hoonkic1262f22013-01-24 21:59:00 -08006759 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006760 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
Lee Hoonkic1262f22013-01-24 21:59:00 -08006761 {
6762 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
6763 we return error code at 'add_station()'. Hence we have this
6764 check again in addtion to add_station().
6765 Anyway, there is no hard to double-check. */
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006766 if (SIR_MAC_TDLS_SETUP_REQ == action_code)
Lee Hoonkic1262f22013-01-24 21:59:00 -08006767 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006768 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6769 "%s: " MAC_ADDRESS_STR
6770 " TDLS Max peer already connected. Request declined.",
6771 __func__, MAC_ADDR_ARRAY(peer));
Gopichand Nakkala05922802013-03-14 12:23:19 -07006772 goto error;
Lee Hoonkic1262f22013-01-24 21:59:00 -08006773 }
6774 else
6775 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006776 /* maximum reached. tweak to send error code to peer and return
6777 error code to supplicant */
Lee Hoonkic1262f22013-01-24 21:59:00 -08006778 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006779 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6780 "%s: " MAC_ADDRESS_STR
6781 " TDLS Max peer already connected send response status %d",
6782 __func__, MAC_ADDR_ARRAY(peer), status_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006783 max_sta_failed = -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006784 /* fall through to send setup resp with failure status
6785 code */
Lee Hoonkic1262f22013-01-24 21:59:00 -08006786 }
6787 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006788 else
6789 {
6790 hddTdlsPeer_t *pTdlsPeer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006791 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006792 if (pTdlsPeer && (eTDLS_LINK_CONNECTED == pTdlsPeer->link_status))
6793 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006794 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6795 "%s:" MAC_ADDRESS_STR " already connected. Request declined.",
6796 __func__, MAC_ADDR_ARRAY(peer));
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006797 return -EPERM;
6798 }
6799 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006800 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006801 vos_mem_copy(peerMac, peer, 6);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006802
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006803#ifdef WLAN_FEATURE_TDLS_DEBUG
6804 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006805 "%s: " MAC_ADDRESS_STR " action %d, dialog_token %d status %d, len = %d",
6806 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
6807 action_code, dialog_token, status_code, len);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006808#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006809
Hoonki Leea34dd892013-02-05 22:56:02 -08006810 /*Except teardown responder will not be used so just make 0*/
6811 responder = 0;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006812 if (SIR_MAC_TDLS_TEARDOWN == action_code)
Hoonki Leea34dd892013-02-05 22:56:02 -08006813 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006814 responder = wlan_hdd_tdls_get_responder(pAdapter, peerMac);
6815 if(-1 == responder)
Hoonki Leea34dd892013-02-05 22:56:02 -08006816 {
6817 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006818 "%s: " MAC_ADDRESS_STR " peer doesn't exist dialog_token %d status %d, len = %d",
6819 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
Hoonki Leea34dd892013-02-05 22:56:02 -08006820 dialog_token, status_code, len);
6821 return -EPERM;
6822 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006823 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006824
Gopichand Nakkala05922802013-03-14 12:23:19 -07006825 /* max_sta_failed ; we didn't set to CONNECTING for this case,
6826 because we already know that this transaction will be failed,
6827 but we weren't sure if supplicant call DISABLE_LINK or not. So,
6828 to be safe, do not change the state mahine.
6829 */
6830 if (max_sta_failed == 0 &&
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006831 (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
Gopichand Nakkala8b00c632013-03-08 19:47:52 -08006832 wlan_hdd_tdls_set_link_status(pAdapter, peerMac, eTDLS_LINK_CONNECTING);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006833
6834 INIT_COMPLETION(pAdapter->tdls_mgmt_comp);
6835
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006836 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
Hoonki Leea34dd892013-02-05 22:56:02 -08006837 peerMac, action_code, dialog_token, status_code, (tANI_U8 *)buf, len, responder);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006838
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006839 if (VOS_STATUS_SUCCESS != status)
6840 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006841 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6842 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006843 goto error;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006844 }
6845
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006846 /* not block discovery request, as it is called from timer callback */
6847 if (SIR_MAC_TDLS_DIS_REQ != action_code)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006848 {
Pervinder Singhb4638422013-03-04 22:51:36 -08006849 long rc;
6850
6851 rc = wait_for_completion_interruptible_timeout(&pAdapter->tdls_mgmt_comp,
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006852 msecs_to_jiffies(WAIT_TIME_TDLS_MGMT));
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006853
Pervinder Singhb4638422013-03-04 22:51:36 -08006854 if ((rc <= 0) || (TRUE != pAdapter->mgmtTxCompletionStatus))
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006855 {
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006856 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pervinder Singhb4638422013-03-04 22:51:36 -08006857 "%s: Mgmt Tx Completion failed status %ld TxCompletion %lu",
6858 __func__, rc, pAdapter->mgmtTxCompletionStatus);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006859 goto error;
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006860 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006861 }
6862
Gopichand Nakkala05922802013-03-14 12:23:19 -07006863 if (max_sta_failed)
6864 return max_sta_failed;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006865
Hoonki Leea34dd892013-02-05 22:56:02 -08006866 if (SIR_MAC_TDLS_SETUP_RSP == action_code)
6867 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006868 wlan_hdd_tdls_set_responder(pAdapter, peerMac, TRUE);
Hoonki Leea34dd892013-02-05 22:56:02 -08006869 }
6870 else if (SIR_MAC_TDLS_SETUP_CNF == action_code)
6871 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006872 wlan_hdd_tdls_set_responder(pAdapter, peerMac, FALSE);
Hoonki Leea34dd892013-02-05 22:56:02 -08006873 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006874
6875 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07006876error:
6877 /* max_sta_failed ; we didn't set to CONNECTING for this case,
6878 because we already know that this transaction will be failed,
6879 but we weren't sure if supplicant call DISABLE_LINK or not. So,
6880 to be safe, do not change the state mahine.
6881 */
6882 if(max_sta_failed == 0 &&
6883 (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
6884 wlan_hdd_tdls_set_link_status(pAdapter, peerMac, eTDLS_LINK_IDLE);
6885 return -EPERM;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006886}
6887
6888static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
6889 u8 *peer, enum nl80211_tdls_operation oper)
6890{
6891 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6892 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006893#ifdef WLAN_FEATURE_TDLS_DEBUG
6894 const char *tdls_oper_str[]= {
6895 "NL80211_TDLS_DISCOVERY_REQ",
6896 "NL80211_TDLS_SETUP",
6897 "NL80211_TDLS_TEARDOWN",
6898 "NL80211_TDLS_ENABLE_LINK",
6899 "NL80211_TDLS_DISABLE_LINK",
6900 "NL80211_TDLS_UNKONW_OPER"};
6901#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006902
6903 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6904 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006905 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006906 "Invalid arguments");
6907 return -EINVAL;
6908 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006909
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006910 if (pHddCtx->isLogpInProgress)
6911 {
6912 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6913 "%s:LOGP in Progress. Ignore!!!", __func__);
6914 return -EBUSY;
6915 }
6916
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006917#ifdef WLAN_FEATURE_TDLS_DEBUG
6918 if((int)oper > 4)
6919 oper = 5;
6920
6921 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006922 "%s: " MAC_ADDRESS_STR " %d (%s) ", "tdls_oper",
6923 MAC_ADDR_ARRAY(peer), (int)oper,
6924 tdls_oper_str[(int)oper]);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006925#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006926
6927 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006928 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006929 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006930 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006931 "TDLS Disabled in INI OR not enabled in FW.\
6932 Cannot process TDLS commands \n");
6933 return -ENOTSUPP;
6934 }
6935
6936 switch (oper) {
6937 case NL80211_TDLS_ENABLE_LINK:
6938 {
Hoonki Lee387663d2013-02-05 18:08:43 -08006939 hddTdlsPeer_t *pTdlsPeer;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006940 VOS_STATUS status;
6941
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006942 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006943
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006944 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
6945 "%s: TDLS_LINK_ENABLE " MAC_ADDRESS_STR,
6946 __func__, MAC_ADDR_ARRAY(peer));
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006947
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006948 if ( NULL == pTdlsPeer ) {
6949 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_hdd_tdls_find_peer "
6950 MAC_ADDRESS_STR " failed",
6951 __func__, MAC_ADDR_ARRAY(peer));
6952 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006953 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006954
6955 if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status)
6956 {
6957 /* start TDLS client registration with TL */
6958 status = hdd_roamRegisterTDLSSTA( pAdapter, peer, pTdlsPeer->staId, pTdlsPeer->signature);
6959 wlan_hdd_tdls_increment_peer_count(pAdapter);
6960 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
6961 wlan_hdd_tdls_check_bmps(pAdapter);
6962 }
6963
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006964 }
6965 break;
6966 case NL80211_TDLS_DISABLE_LINK:
Lee Hoonkic1262f22013-01-24 21:59:00 -08006967 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006968 hddTdlsPeer_t *curr_peer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006969
6970 if(NULL != curr_peer)
Lee Hoonkic1262f22013-01-24 21:59:00 -08006971 {
6972 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
6973 pAdapter->sessionId, peer );
Gopichand Nakkala8b00c632013-03-08 19:47:52 -08006974 wlan_hdd_tdls_set_peer_link_status(curr_peer, eTDLS_LINK_IDLE);
Lee Hoonkic1262f22013-01-24 21:59:00 -08006975 }
6976 else
6977 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006978 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6979 "%s: TDLS Peer Station doesn't exist.", __func__);
Lee Hoonkic1262f22013-01-24 21:59:00 -08006980 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006981 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006982 break;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006983 case NL80211_TDLS_TEARDOWN:
6984 case NL80211_TDLS_SETUP:
6985 case NL80211_TDLS_DISCOVERY_REQ:
6986 /* We don't support in-driver setup/teardown/discovery */
6987 return -ENOTSUPP;
6988 default:
6989 return -ENOTSUPP;
6990 }
6991 return 0;
6992}
Chilam NG571c65a2013-01-19 12:27:36 +05306993
6994int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
6995 struct net_device *dev, u8 *peer)
6996{
6997 hddLog(VOS_TRACE_LEVEL_INFO, "tdls send discover req: %x %x %x %x %x %x",
6998 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5]);
6999
7000 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
7001 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
7002}
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007003#endif
7004
Jeff Johnson295189b2012-06-20 16:38:30 -07007005/* cfg80211_ops */
7006static struct cfg80211_ops wlan_hdd_cfg80211_ops =
7007{
7008 .add_virtual_intf = wlan_hdd_add_virtual_intf,
7009 .del_virtual_intf = wlan_hdd_del_virtual_intf,
7010 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
7011 .change_station = wlan_hdd_change_station,
7012#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
7013 .add_beacon = wlan_hdd_cfg80211_add_beacon,
7014 .del_beacon = wlan_hdd_cfg80211_del_beacon,
7015 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007016#else
7017 .start_ap = wlan_hdd_cfg80211_start_ap,
7018 .change_beacon = wlan_hdd_cfg80211_change_beacon,
7019 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07007020#endif
7021 .change_bss = wlan_hdd_cfg80211_change_bss,
7022 .add_key = wlan_hdd_cfg80211_add_key,
7023 .get_key = wlan_hdd_cfg80211_get_key,
7024 .del_key = wlan_hdd_cfg80211_del_key,
7025 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08007026#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07007027 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08007028#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007029 .scan = wlan_hdd_cfg80211_scan,
7030 .connect = wlan_hdd_cfg80211_connect,
7031 .disconnect = wlan_hdd_cfg80211_disconnect,
7032 .join_ibss = wlan_hdd_cfg80211_join_ibss,
7033 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
7034 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
7035 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
7036 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
Jeff Johnson295189b2012-06-20 16:38:30 -07007037 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
7038 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
7039 .mgmt_tx = wlan_hdd_action,
7040#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7041 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
7042 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
7043 .set_txq_params = wlan_hdd_set_txq_params,
7044#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007045 .get_station = wlan_hdd_cfg80211_get_station,
7046 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
7047 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007048 .add_station = wlan_hdd_cfg80211_add_station,
7049#ifdef FEATURE_WLAN_LFR
7050 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
7051 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
7052 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
7053#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007054#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
7055 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
7056#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007057#ifdef FEATURE_WLAN_TDLS
7058 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
7059 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
7060#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007061};
7062