blob: 2b99eb3a74de41d44332a1abd580ad6ce302e024 [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 {
1429 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1430
1431 if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
1432 {
1433 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
1434
1435 /* If auto channel selection is configured as enable/ 1 then ignore
1436 channel set by supplicant
1437 */
1438 if ( cfg_param->apAutoChannelSelection )
1439 {
1440 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = AUTO_CHANNEL_SELECT;
1441
1442 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1443 "%s: set channel to auto channel (0) for device mode =%d",
1444 __func__, pAdapter->device_mode);
1445 }
1446 }
1447 }
1448 else
1449 {
1450 hddLog(VOS_TRACE_LEVEL_FATAL,
1451 "%s: Invalid device mode failed to set valid channel", __func__);
1452 return -EINVAL;
1453 }
1454 EXIT();
1455 return 0;
1456}
1457
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301458/*
1459 * FUNCTION: wlan_hdd_select_cbmode
1460 * called by wlan_hdd_cfg80211_start_bss() and
1461 * This function selects the cbmode based on primary channel
1462 */
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001463VOS_STATUS wlan_sap_select_cbmode(void *pAdapter,eSapPhyMode SapHw_mode, v_U8_t channel)
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301464{
1465 tSmeConfigParams smeConfig;
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001466 hdd_context_t *pHddCtx = ( hdd_context_t *) pAdapter;
1467 hdd_config_t *pConfigIni = ((hdd_context_t *)(pAdapter))->cfg_ini;
1468
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301469 if(
1470#ifdef WLAN_FEATURE_11AC
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001471 SapHw_mode != eSAP_DOT11_MODE_11ac &&
1472 SapHw_mode != eSAP_DOT11_MODE_11ac_ONLY &&
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301473#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001474 SapHw_mode != eSAP_DOT11_MODE_11n &&
1475 SapHw_mode != eSAP_DOT11_MODE_11n_ONLY
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301476 )
1477 {
1478 return VOS_STATUS_SUCCESS;
1479 }
1480
1481 if (!pConfigIni->nChannelBondingMode5GHz) {
1482 return VOS_STATUS_SUCCESS;
1483 }
1484
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001485 //channel = pSapConfig->channel;
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301486 vos_mem_zero(&smeConfig, sizeof (tSmeConfigParams));
1487
1488 sme_GetConfigParam(pHddCtx->hHal, &smeConfig);
1489
1490#ifdef WLAN_FEATURE_11AC
1491
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001492 if ( SapHw_mode == eSAP_DOT11_MODE_11ac ||
1493 SapHw_mode == eSAP_DOT11_MODE_11ac_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301494 {
1495 if ( channel== 36 || channel == 52 || channel == 100 ||
1496 channel == 116 || channel == 149 )
1497 {
1498 smeConfig.csrConfig.channelBondingMode5GHz =
1499 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW - 1;
1500 }
1501 else if ( channel == 40 || channel == 56 || channel == 104 ||
1502 channel == 120 || channel == 153 )
1503 {
1504 smeConfig.csrConfig.channelBondingMode5GHz =
1505 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW - 1;
1506 }
1507 else if ( channel == 44 || channel == 60 || channel == 108 ||
1508 channel == 124 || channel == 157 )
1509 {
1510 smeConfig.csrConfig.channelBondingMode5GHz =
1511 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH -1;
1512 }
1513 else if ( channel == 48 || channel == 64 || channel == 112 ||
1514 channel == 128 || channel == 161 )
1515 {
1516 smeConfig.csrConfig.channelBondingMode5GHz =
1517 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH - 1;
1518 }
Shailender Karmuchi84f11f02013-02-12 17:11:45 -08001519 else if ( channel == 165 )
1520 {
1521 smeConfig.csrConfig.channelBondingMode5GHz = 0;
1522 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301523 }
1524#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001525 if ( SapHw_mode == eSAP_DOT11_MODE_11n ||
1526 SapHw_mode == eSAP_DOT11_MODE_11n_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301527 {
1528 if ( channel== 40 || channel == 48 || channel == 56 ||
1529 channel == 64 || channel == 104 || channel == 112 ||
1530 channel == 120 || channel == 128 || channel == 136 ||
1531 channel == 144 || channel == 153 || channel == 161 )
1532 {
1533 smeConfig.csrConfig.channelBondingMode5GHz = 1;
1534 }
1535 else if ( channel== 36 || channel == 44 || channel == 52 ||
1536 channel == 60 || channel == 100 || channel == 108 ||
1537 channel == 116 || channel == 124 || channel == 132 ||
1538 channel == 140 || channel == 149 || channel == 157 )
1539 {
1540 smeConfig.csrConfig.channelBondingMode5GHz = 2;
1541 }
Shailender Karmuchi84f11f02013-02-12 17:11:45 -08001542 else if ( channel == 165 )
1543 {
1544 smeConfig.csrConfig.channelBondingMode5GHz = 0;
1545 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301546 }
1547 pr_info ("cbmode selected=%ld\n",smeConfig.csrConfig.channelBondingMode5GHz);
1548
1549 sme_UpdateConfig (pHddCtx->hHal,&smeConfig);
1550 return VOS_STATUS_SUCCESS;
1551}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001552
Jeff Johnson295189b2012-06-20 16:38:30 -07001553#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1554static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1555 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001556#else
1557static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1558 struct cfg80211_beacon_data *params,
1559 const u8 *ssid, size_t ssid_len,
1560 enum nl80211_hidden_ssid hidden_ssid)
1561#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001562{
1563 tsap_Config_t *pConfig;
1564 beacon_data_t *pBeacon = NULL;
1565 struct ieee80211_mgmt *pMgmt_frame;
1566 v_U8_t *pIe=NULL;
1567 v_U16_t capab_info;
1568 eCsrAuthType RSNAuthType;
1569 eCsrEncryptionType RSNEncryptType;
1570 eCsrEncryptionType mcRSNEncryptType;
1571 int status = VOS_STATUS_SUCCESS;
1572 tpWLAN_SAPEventCB pSapEventCallback;
1573 hdd_hostapd_state_t *pHostapdState;
1574 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1575 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301576 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001577 struct qc_mac_acl_entry *acl_entry = NULL;
1578 v_SINT_t i;
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001579 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001580
1581 ENTER();
1582
1583 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1584
1585 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1586
1587 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1588
1589 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1590
1591 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1592
1593 //channel is already set in the set_channel Call back
1594 //pConfig->channel = pCommitConfig->channel;
1595
1596 /*Protection parameter to enable or disable*/
1597 pConfig->protEnabled =
1598 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1599
1600 pConfig->dtim_period = pBeacon->dtim_period;
1601
1602 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1603 pConfig->dtim_period);
1604
1605
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001606 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001607 {
1608 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001609 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001610 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001611 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001612 tANI_BOOLEAN restartNeeded;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001613 pConfig->ieee80211d = 1;
1614 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1615 sme_setRegInfo(hHal, pConfig->countryCode);
1616 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
Jeff Johnson295189b2012-06-20 16:38:30 -07001617 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001618 else
1619 {
1620 pConfig->ieee80211d = 0;
1621 }
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301622 /*
1623 * If auto channel is configured i.e. channel is 0,
1624 * so skip channel validation.
1625 */
1626 if( AUTO_CHANNEL_SELECT != pConfig->channel )
1627 {
1628 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1629 {
1630 hddLog(VOS_TRACE_LEVEL_ERROR,
1631 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1632 return -EINVAL;
1633 }
1634 }
1635 else
1636 {
1637 if(1 != pHddCtx->is_dynamic_channel_range_set)
1638 {
1639 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
1640 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
1641 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
1642 }
1643 pHddCtx->is_dynamic_channel_range_set = 0;
1644 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001645 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001646 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001647 {
1648 pConfig->ieee80211d = 0;
1649 }
1650 pConfig->authType = eSAP_AUTO_SWITCH;
1651
1652 capab_info = pMgmt_frame->u.beacon.capab_info;
1653
1654 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
1655 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1656
1657 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1658
1659 /*Set wps station to configured*/
1660 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1661
1662 if(pIe)
1663 {
1664 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1665 {
1666 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1667 return -EINVAL;
1668 }
1669 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1670 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001671 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001672 /* Check 15 bit of WPS IE as it contain information for wps state
1673 * WPS state
1674 */
1675 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1676 {
1677 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1678 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1679 {
1680 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1681 }
1682 }
1683 }
1684 else
1685 {
1686 pConfig->wps_state = SAP_WPS_DISABLED;
1687 }
1688 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
1689
1690 pConfig->RSNWPAReqIELength = 0;
1691 pConfig->pRSNWPAReqIE = NULL;
1692 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1693 WLAN_EID_RSN);
1694 if(pIe && pIe[1])
1695 {
1696 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1697 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1698 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1699 /* The actual processing may eventually be more extensive than
1700 * this. Right now, just consume any PMKIDs that are sent in
1701 * by the app.
1702 * */
1703 status = hdd_softap_unpackIE(
1704 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1705 &RSNEncryptType,
1706 &mcRSNEncryptType,
1707 &RSNAuthType,
1708 pConfig->pRSNWPAReqIE[1]+2,
1709 pConfig->pRSNWPAReqIE );
1710
1711 if( VOS_STATUS_SUCCESS == status )
1712 {
1713 /* Now copy over all the security attributes you have
1714 * parsed out
1715 * */
1716 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1717 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1718 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1719 = RSNEncryptType;
1720 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1721 "EncryptionType = %d mcEncryptionType = %d\n"),
1722 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1723 }
1724 }
1725
1726 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1727 pBeacon->tail, pBeacon->tail_len);
1728
1729 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1730 {
1731 if (pConfig->pRSNWPAReqIE)
1732 {
1733 /*Mixed mode WPA/WPA2*/
1734 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1735 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1736 }
1737 else
1738 {
1739 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1740 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1741 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1742 status = hdd_softap_unpackIE(
1743 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1744 &RSNEncryptType,
1745 &mcRSNEncryptType,
1746 &RSNAuthType,
1747 pConfig->pRSNWPAReqIE[1]+2,
1748 pConfig->pRSNWPAReqIE );
1749
1750 if( VOS_STATUS_SUCCESS == status )
1751 {
1752 /* Now copy over all the security attributes you have
1753 * parsed out
1754 * */
1755 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1756 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1757 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1758 = RSNEncryptType;
1759 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1760 "EncryptionType = %d mcEncryptionType = %d\n"),
1761 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1762 }
1763 }
1764 }
1765
1766 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1767
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001768#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001769 if (params->ssid != NULL)
1770 {
1771 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1772 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1773 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1774 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1775 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001776#else
1777 if (ssid != NULL)
1778 {
1779 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1780 pConfig->SSIDinfo.ssid.length = ssid_len;
1781 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1782 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1783 }
1784#endif
1785
Jeff Johnson295189b2012-06-20 16:38:30 -07001786 vos_mem_copy(pConfig->self_macaddr.bytes,
1787 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1788
1789 /* default value */
1790 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1791 pConfig->num_accept_mac = 0;
1792 pConfig->num_deny_mac = 0;
1793
1794 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1795 pBeacon->tail, pBeacon->tail_len);
1796
1797 /* pIe for black list is following form:
1798 type : 1 byte
1799 length : 1 byte
1800 OUI : 4 bytes
1801 acl type : 1 byte
1802 no of mac addr in black list: 1 byte
1803 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1804 */
1805 if ((pIe != NULL) && (pIe[1] != 0))
1806 {
1807 pConfig->SapMacaddr_acl = pIe[6];
1808 pConfig->num_deny_mac = pIe[7];
1809 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1810 pIe[6], pIe[7]);
1811 if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
1812 pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
1813 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1814 for (i = 0; i < pConfig->num_deny_mac; i++)
1815 {
1816 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1817 acl_entry++;
1818 }
1819 }
1820 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1821 pBeacon->tail, pBeacon->tail_len);
1822
1823 /* pIe for white list is following form:
1824 type : 1 byte
1825 length : 1 byte
1826 OUI : 4 bytes
1827 acl type : 1 byte
1828 no of mac addr in white list: 1 byte
1829 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1830 */
1831 if ((pIe != NULL) && (pIe[1] != 0))
1832 {
1833 pConfig->SapMacaddr_acl = pIe[6];
1834 pConfig->num_accept_mac = pIe[7];
1835 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
1836 pIe[6], pIe[7]);
1837 if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
1838 pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
1839 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1840 for (i = 0; i < pConfig->num_accept_mac; i++)
1841 {
1842 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1843 acl_entry++;
1844 }
1845 }
1846 wlan_hdd_set_sapHwmode(pHostapdAdapter);
1847
Jeff Johnsone7245742012-09-05 17:12:55 -07001848#ifdef WLAN_FEATURE_11AC
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08001849 /* Overwrite the hostapd setting for HW mode only for 11ac.
1850 * This is valid only if mode is set to 11n in hostapd and either AUTO or 11ac in .ini .
1851 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode) */
1852 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
1853 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
1854 (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
1855 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1856 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07001857 {
1858 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
1859 }
1860#endif
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301861
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001862 if( AUTO_CHANNEL_SELECT != pConfig->channel)
1863 wlan_sap_select_cbmode((WLAN_HDD_GET_CTX(pHostapdAdapter)),pConfig->SapHw_mode,pConfig->channel);
Jeff Johnson295189b2012-06-20 16:38:30 -07001864 // ht_capab is not what the name conveys,this is used for protection bitmap
1865 pConfig->ht_capab =
1866 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
1867
1868 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
1869 {
1870 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
1871 return -EINVAL;
1872 }
1873
1874 //Uapsd Enabled Bit
1875 pConfig->UapsdEnable =
1876 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
1877 //Enable OBSS protection
1878 pConfig->obssProtEnabled =
1879 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
1880
1881 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
1882 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
1883 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
1884 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
1885 (int)pConfig->channel);
1886 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
1887 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
1888 pConfig->authType);
1889 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
1890 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
1891 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
1892 pConfig->protEnabled, pConfig->obssProtEnabled);
1893
1894 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
1895 {
1896 //Bss already started. just return.
1897 //TODO Probably it should update some beacon params.
1898 hddLog( LOGE, "Bss Already started...Ignore the request");
1899 EXIT();
1900 return 0;
1901 }
1902
1903 pConfig->persona = pHostapdAdapter->device_mode;
1904
1905 pSapEventCallback = hdd_hostapd_SAPEventCB;
1906 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
1907 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
1908 {
1909 hddLog(LOGE,FL("SAP Start Bss fail\n"));
1910 return -EINVAL;
1911 }
1912
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001913 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07001914 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
1915
1916 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1917
1918 if (!VOS_IS_STATUS_SUCCESS(status))
1919 {
1920 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1921 ("ERROR: HDD vos wait for single_event failed!!\n"));
1922 VOS_ASSERT(0);
1923 }
1924
1925 //Succesfully started Bss update the state bit.
1926 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
1927
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001928#ifdef WLAN_FEATURE_P2P_DEBUG
1929 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
1930 {
1931 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
1932 {
1933 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1934 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001935 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001936 }
1937 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
1938 {
1939 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1940 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001941 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001942 }
1943 }
1944#endif
1945
Jeff Johnson295189b2012-06-20 16:38:30 -07001946 pHostapdState->bCommit = TRUE;
1947 EXIT();
1948
1949 return 0;
1950}
1951
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001952#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001953static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
1954 struct net_device *dev,
1955 struct beacon_parameters *params)
1956{
1957 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1958 int status=VOS_STATUS_SUCCESS;
1959
1960 ENTER();
1961
1962 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
1963
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001964 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1965 {
1966 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1967 "%s:LOGP in Progress. Ignore!!!", __func__);
1968 return -EAGAIN;
1969 }
1970
Jeff Johnson295189b2012-06-20 16:38:30 -07001971 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07001972 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07001973 )
1974 {
1975 beacon_data_t *old,*new;
1976
1977 old = pAdapter->sessionCtx.ap.beacon;
1978
1979 if (old)
1980 return -EALREADY;
1981
1982 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
1983
1984 if(status != VOS_STATUS_SUCCESS)
1985 {
1986 hddLog(VOS_TRACE_LEVEL_FATAL,
1987 "%s:Error!!! Allocating the new beacon\n",__func__);
1988 return -EINVAL;
1989 }
1990
1991 pAdapter->sessionCtx.ap.beacon = new;
1992
1993 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
1994 }
1995
1996 EXIT();
1997 return status;
1998}
1999
2000static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
2001 struct net_device *dev,
2002 struct beacon_parameters *params)
2003{
2004 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2005 int status=VOS_STATUS_SUCCESS;
2006
2007 ENTER();
2008
2009 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2010 __func__,pAdapter->device_mode);
2011
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002012 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2013 {
2014 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2015 "%s:LOGP in Progress. Ignore!!!", __func__);
2016 return -EAGAIN;
2017 }
2018
Jeff Johnson295189b2012-06-20 16:38:30 -07002019 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002020 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002021 )
2022 {
2023 beacon_data_t *old,*new;
2024
2025 old = pAdapter->sessionCtx.ap.beacon;
2026
2027 if (!old)
2028 return -ENOENT;
2029
2030 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2031
2032 if(status != VOS_STATUS_SUCCESS) {
2033 hddLog(VOS_TRACE_LEVEL_FATAL,
2034 "%s: Error!!! Allocating the new beacon\n",__func__);
2035 return -EINVAL;
2036 }
2037
2038 pAdapter->sessionCtx.ap.beacon = new;
2039
2040 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2041 }
2042
2043 EXIT();
2044 return status;
2045}
2046
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002047#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
2048
2049#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002050static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
2051 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002052#else
2053static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
2054 struct net_device *dev)
2055#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002056{
2057 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07002058 hdd_context_t *pHddCtx = NULL;
2059 hdd_scaninfo_t *pScanInfo = NULL;
2060 hdd_adapter_t *staAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002061 VOS_STATUS status = 0;
2062
2063 ENTER();
2064
2065 if (NULL == pAdapter)
2066 {
2067 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002068 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002069 return -ENODEV;
2070 }
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002071 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2072 {
2073 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2074 "%s:LOGP in Progress. Ignore!!!", __func__);
2075 return -EAGAIN;
2076 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002077
2078 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2079 if (NULL == pHddCtx)
2080 {
2081 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002082 "%s: HDD context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002083 return -ENODEV;
2084 }
2085
2086 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
2087 if (NULL == staAdapter)
2088 {
2089 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
2090 if (NULL == staAdapter)
2091 {
2092 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002093 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002094 return -ENODEV;
2095 }
2096 }
2097
2098 pScanInfo = &pHddCtx->scan_info;
2099
Jeff Johnson295189b2012-06-20 16:38:30 -07002100 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2101 {
2102 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2103 return -EAGAIN;
2104 }
2105
2106 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2107
2108 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2109 __func__,pAdapter->device_mode);
2110
Jeff Johnsone7245742012-09-05 17:12:55 -07002111 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
2112 {
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002113 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Jeff Johnsone7245742012-09-05 17:12:55 -07002114 hdd_abort_mac_scan(staAdapter->pHddCtx);
2115 status = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002116 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07002117 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
2118 if (!status)
2119 {
2120 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson902c9832012-12-10 14:28:09 -08002121 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002122 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07002123 VOS_ASSERT(pScanInfo->mScanPending);
2124 return 0;
2125 }
2126 }
2127
Jeff Johnson295189b2012-06-20 16:38:30 -07002128 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002129 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002130 )
2131 {
2132 beacon_data_t *old;
2133
2134 old = pAdapter->sessionCtx.ap.beacon;
2135
2136 if (!old)
2137 return -ENOENT;
2138
Jeff Johnson295189b2012-06-20 16:38:30 -07002139 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002140
2141 mutex_lock(&pHddCtx->sap_lock);
2142 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2143 {
2144 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss((WLAN_HDD_GET_CTX(pAdapter))->pvosContext) ) )
2145 {
2146 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2147
2148 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2149
2150 if (!VOS_IS_STATUS_SUCCESS(status))
2151 {
2152 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2153 ("ERROR: HDD vos wait for single_event failed!!\n"));
2154 VOS_ASSERT(0);
2155 }
2156 }
2157 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2158 }
2159 mutex_unlock(&pHddCtx->sap_lock);
2160
2161 if(status != VOS_STATUS_SUCCESS)
2162 {
2163 hddLog(VOS_TRACE_LEVEL_FATAL,
2164 "%s:Error!!! Stopping the BSS\n",__func__);
2165 return -EINVAL;
2166 }
2167
2168 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2169 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
2170 ==eHAL_STATUS_FAILURE)
2171 {
2172 hddLog(LOGE,
2173 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
2174 }
2175
2176 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2177 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2178 eANI_BOOLEAN_FALSE) )
2179 {
2180 hddLog(LOGE,
2181 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
2182 }
2183
2184 // Reset WNI_CFG_PROBE_RSP Flags
2185 wlan_hdd_reset_prob_rspies(pAdapter);
2186
2187 pAdapter->sessionCtx.ap.beacon = NULL;
2188 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002189#ifdef WLAN_FEATURE_P2P_DEBUG
2190 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
2191 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
2192 {
2193 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
2194 "GO got removed");
2195 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
2196 }
2197#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002198 }
2199 EXIT();
2200 return status;
2201}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002202
2203#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2204
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302205static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2206 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002207 struct cfg80211_ap_settings *params)
2208{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302209 hdd_adapter_t *pAdapter;
2210 hdd_context_t *pHddCtx;
2211 int status = 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002212
2213 ENTER();
2214
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302215 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002216 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302217 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2218 "%s: Device is Null", __func__);
2219 return -ENODEV;
2220 }
2221
2222 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2223 if (NULL == pAdapter)
2224 {
2225 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2226 "%s: HDD adapter is Null", __func__);
2227 return -ENODEV;
2228 }
2229
2230 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2231 {
2232 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2233 "%s: HDD adapter magic is invalid", __func__);
2234 return -ENODEV;
2235 }
2236
2237 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2238 if (NULL == pHddCtx)
2239 {
2240 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2241 "%s: HDD context is Null", __func__);
2242 return -ENODEV;
2243 }
2244
2245 if (pHddCtx->isLogpInProgress)
2246 {
2247 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2248 "%s: LOGP in Progress. Ignore!!!", __func__);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002249 return -EAGAIN;
2250 }
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302251
2252 if (pHddCtx->isLoadUnloadInProgress)
2253 {
2254 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2255 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
2256 return -EAGAIN;
2257 }
2258
2259 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2260 __func__, pAdapter->device_mode);
2261
2262 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002263 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002264 )
2265 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302266 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002267
2268 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302269
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002270 if (old)
2271 return -EALREADY;
2272
2273 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2274
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302275 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002276 {
2277 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302278 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002279 return -EINVAL;
2280 }
2281 pAdapter->sessionCtx.ap.beacon = new;
Viral Modi3a32cc52013-02-08 11:14:52 -08002282#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2283 wlan_hdd_cfg80211_set_channel(wiphy, dev, params->channel, params->channel_type);
2284#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002285 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2286 params->ssid_len, params->hidden_ssid);
2287 }
2288
2289 EXIT();
2290 return status;
2291}
2292
2293
2294static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
2295 struct net_device *dev,
2296 struct cfg80211_beacon_data *params)
2297{
2298 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2299 int status=VOS_STATUS_SUCCESS;
2300
2301 ENTER();
2302
2303 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2304 __func__, pAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002305 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2306 {
2307 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2308 return -EAGAIN;
2309 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002310
2311 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002312 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002313 )
2314 {
2315 beacon_data_t *old,*new;
2316
2317 old = pAdapter->sessionCtx.ap.beacon;
2318
2319 if (!old)
2320 return -ENOENT;
2321
2322 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2323
2324 if(status != VOS_STATUS_SUCCESS) {
2325 hddLog(VOS_TRACE_LEVEL_FATAL,
2326 "%s: Error!!! Allocating the new beacon\n",__func__);
2327 return -EINVAL;
2328 }
2329
2330 pAdapter->sessionCtx.ap.beacon = new;
2331
2332 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2333 }
2334
2335 EXIT();
2336 return status;
2337}
2338
2339#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2340
Jeff Johnson295189b2012-06-20 16:38:30 -07002341
2342static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2343 struct net_device *dev,
2344 struct bss_parameters *params)
2345{
2346 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2347
2348 ENTER();
2349
2350 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2351 __func__,pAdapter->device_mode);
2352
2353 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002354 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002355 )
2356 {
2357 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2358 * want to update this parameter */
2359 if (-1 != params->ap_isolate)
2360 {
2361 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
2362 }
2363 }
2364
2365 EXIT();
2366 return 0;
2367}
2368
2369/*
2370 * FUNCTION: wlan_hdd_cfg80211_change_iface
2371 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2372 */
2373int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2374 struct net_device *ndev,
2375 enum nl80211_iftype type,
2376 u32 *flags,
2377 struct vif_params *params
2378 )
2379{
2380 struct wireless_dev *wdev;
2381 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2382 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002383 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002384 tCsrRoamProfile *pRoamProfile = NULL;
2385 eCsrRoamBssType LastBSSType;
2386 hdd_config_t *pConfig = pHddCtx->cfg_ini;
2387 eMib_dot11DesiredBssType connectedBssType;
2388 VOS_STATUS status;
2389
2390 ENTER();
2391
2392 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2393 {
2394 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2395 return -EAGAIN;
2396 }
2397
2398 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2399 __func__, pAdapter->device_mode);
2400
2401 wdev = ndev->ieee80211_ptr;
2402
2403#ifdef WLAN_BTAMP_FEATURE
2404 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2405 (NL80211_IFTYPE_ADHOC == type)||
2406 (NL80211_IFTYPE_AP == type)||
2407 (NL80211_IFTYPE_P2P_GO == type))
2408 {
2409 pHddCtx->isAmpAllowed = VOS_FALSE;
2410 // stop AMP traffic
2411 status = WLANBAP_StopAmp();
2412 if(VOS_STATUS_SUCCESS != status )
2413 {
2414 pHddCtx->isAmpAllowed = VOS_TRUE;
2415 hddLog(VOS_TRACE_LEVEL_FATAL,
2416 "%s: Failed to stop AMP", __func__);
2417 return -EINVAL;
2418 }
2419 }
2420#endif //WLAN_BTAMP_FEATURE
2421 /* Reset the current device mode bit mask*/
2422 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2423
2424 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07002425 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002426 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002427 )
2428 {
2429 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2430 pRoamProfile = &pWextState->roamProfile;
2431 LastBSSType = pRoamProfile->BSSType;
2432
2433 switch (type)
2434 {
2435 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002436 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002437 hddLog(VOS_TRACE_LEVEL_INFO,
2438 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2439 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002440#ifdef WLAN_FEATURE_11AC
2441 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2442 {
2443 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2444 }
2445#endif
2446 pRoamProfile->phyMode =
2447 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002448 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002449 //Check for sub-string p2p to confirm its a p2p interface
2450 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002451 {
2452 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2453 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2454 }
2455 else
2456 {
2457 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002458 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002459 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002460 break;
2461 case NL80211_IFTYPE_ADHOC:
2462 hddLog(VOS_TRACE_LEVEL_INFO,
2463 "%s: setting interface Type to ADHOC", __func__);
2464 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2465 pRoamProfile->phyMode =
2466 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
2467 wdev->iftype = type;
2468 break;
2469
2470 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002471 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002472 {
2473 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2474 "%s: setting interface Type to %s", __func__,
2475 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2476
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002477 //Cancel any remain on channel for GO mode
2478 if (NL80211_IFTYPE_P2P_GO == type)
2479 {
2480 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2481 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002482 if (NL80211_IFTYPE_AP == type)
2483 {
2484 /* As Loading WLAN Driver one interface being created for p2p device
2485 * address. This will take one HW STA and the max number of clients
2486 * that can connect to softAP will be reduced by one. so while changing
2487 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2488 * interface as it is not required in SoftAP mode.
2489 */
2490
2491 // Get P2P Adapter
2492 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2493
2494 if (pP2pAdapter)
2495 {
2496 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2497 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2498 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2499 }
2500 }
2501
Jeff Johnson295189b2012-06-20 16:38:30 -07002502 //De-init the adapter.
2503 hdd_stop_adapter( pHddCtx, pAdapter );
2504 hdd_deinit_adapter( pHddCtx, pAdapter );
2505 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
Jeff Johnson295189b2012-06-20 16:38:30 -07002506 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2507 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002508
2509 //Disable BMPS and IMPS if enabled
2510 //before starting Go
2511 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2512 {
2513 if(VOS_STATUS_E_FAILURE ==
2514 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2515 {
2516 //Fail to Exit BMPS
2517 VOS_ASSERT(0);
2518 }
2519 }
2520
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002521 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2522 (pConfig->apRandomBssidEnabled))
2523 {
2524 /* To meet Android requirements create a randomized
2525 MAC address of the form 02:1A:11:Fx:xx:xx */
2526 get_random_bytes(&ndev->dev_addr[3], 3);
2527 ndev->dev_addr[0] = 0x02;
2528 ndev->dev_addr[1] = 0x1A;
2529 ndev->dev_addr[2] = 0x11;
2530 ndev->dev_addr[3] |= 0xF0;
2531 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2532 VOS_MAC_ADDR_SIZE);
2533 pr_info("wlan: Generated HotSpot BSSID "
2534 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2535 ndev->dev_addr[0],
2536 ndev->dev_addr[1],
2537 ndev->dev_addr[2],
2538 ndev->dev_addr[3],
2539 ndev->dev_addr[4],
2540 ndev->dev_addr[5]);
2541 }
2542
Jeff Johnson295189b2012-06-20 16:38:30 -07002543 hdd_set_ap_ops( pAdapter->dev );
2544
2545 status = hdd_init_ap_mode(pAdapter);
2546 if(status != VOS_STATUS_SUCCESS)
2547 {
2548 hddLog(VOS_TRACE_LEVEL_FATAL,
2549 "%s: Error initializing the ap mode", __func__);
2550 return -EINVAL;
2551 }
2552 hdd_set_conparam(1);
2553
Jeff Johnson295189b2012-06-20 16:38:30 -07002554 /*interface type changed update in wiphy structure*/
2555 if(wdev)
2556 {
2557 wdev->iftype = type;
2558 pHddCtx->change_iface = type;
2559 }
2560 else
2561 {
2562 hddLog(VOS_TRACE_LEVEL_ERROR,
2563 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2564 return -EINVAL;
2565 }
2566 goto done;
2567 }
2568
2569 default:
2570 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2571 __func__);
2572 return -EOPNOTSUPP;
2573 }
2574 }
2575 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002576 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002577 )
2578 {
2579 switch(type)
2580 {
2581 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002582 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002583 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002584 hdd_stop_adapter( pHddCtx, pAdapter );
2585 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002586 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002587 //Check for sub-string p2p to confirm its a p2p interface
2588 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002589 {
2590 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2591 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2592 }
2593 else
2594 {
2595 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002596 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002597 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002598 hdd_set_conparam(0);
2599 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002600 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2601 hdd_set_station_ops( pAdapter->dev );
2602 status = hdd_init_station_mode( pAdapter );
2603 if( VOS_STATUS_SUCCESS != status )
2604 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002605 /* In case of JB, for P2P-GO, only change interface will be called,
2606 * This is the right place to enable back bmps_imps()
2607 */
2608 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002609 goto done;
2610 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002611 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002612 wdev->iftype = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002613 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2614 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07002615 goto done;
2616 default:
2617 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2618 __func__);
2619 return -EOPNOTSUPP;
2620
2621 }
2622
2623 }
2624 else
2625 {
2626 return -EOPNOTSUPP;
2627 }
2628
2629
2630 if(pRoamProfile)
2631 {
2632 if ( LastBSSType != pRoamProfile->BSSType )
2633 {
2634 /*interface type changed update in wiphy structure*/
2635 wdev->iftype = type;
2636
2637 /*the BSS mode changed, We need to issue disconnect
2638 if connected or in IBSS disconnect state*/
2639 if ( hdd_connGetConnectedBssType(
2640 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2641 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2642 {
2643 /*need to issue a disconnect to CSR.*/
2644 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2645 if( eHAL_STATUS_SUCCESS ==
2646 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2647 pAdapter->sessionId,
2648 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2649 {
2650 wait_for_completion_interruptible_timeout(
2651 &pAdapter->disconnect_comp_var,
2652 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2653 }
2654 }
2655 }
2656 }
2657
2658done:
2659 /*set bitmask based on updated value*/
2660 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
2661#ifdef WLAN_BTAMP_FEATURE
2662 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
2663 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2664 {
2665 //we are ok to do AMP
2666 pHddCtx->isAmpAllowed = VOS_TRUE;
2667 }
2668#endif //WLAN_BTAMP_FEATURE
2669 EXIT();
2670 return 0;
2671}
2672
2673static int wlan_hdd_change_station(struct wiphy *wiphy,
2674 struct net_device *dev,
2675 u8 *mac,
2676 struct station_parameters *params)
2677{
2678 VOS_STATUS status = VOS_STATUS_SUCCESS;
2679 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2680 v_MACADDR_t STAMacAddress;
2681
Jeff Johnsone7245742012-09-05 17:12:55 -07002682 ENTER();
2683
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002684 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2685 {
2686 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2687 "%s:LOGP in Progress. Ignore!!!", __func__);
2688 return -EAGAIN;
2689 }
2690
Jeff Johnson295189b2012-06-20 16:38:30 -07002691 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
2692
2693 if ( ( pAdapter->device_mode == WLAN_HDD_SOFTAP )
Jeff Johnson295189b2012-06-20 16:38:30 -07002694 || ( pAdapter->device_mode == WLAN_HDD_P2P_GO )
Jeff Johnson295189b2012-06-20 16:38:30 -07002695 )
2696 {
2697 if(params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
2698 {
2699 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
2700 WLANTL_STA_AUTHENTICATED);
2701
2702 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002703 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002704 return -EINVAL;
2705 }
2706 }
2707
Jeff Johnsone7245742012-09-05 17:12:55 -07002708 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002709 return status;
2710}
2711
2712/*
2713 * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
2714 * This function is used to get peer station index in IBSS mode
2715 */
2716static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
2717{
2718 u8 idx = 0;
2719 u8 temp[VOS_MAC_ADDR_SIZE] = {0};
2720 ENTER();
2721 memset(temp, 0, VOS_MAC_ADDR_SIZE);
2722 for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
2723 {
2724 if ( (0 !=
2725 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
2726 && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
2727 temp, VOS_MAC_ADDR_SIZE)
2728 )
2729 {
2730 return idx;
2731 }
2732 }
2733 return idx;
2734}
2735
2736
2737/*
2738 * FUNCTION: wlan_hdd_cfg80211_add_key
2739 * This function is used to initialize the key information
2740 */
2741#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2742static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2743 struct net_device *ndev,
2744 u8 key_index, bool pairwise,
2745 const u8 *mac_addr,
2746 struct key_params *params
2747 )
2748#else
2749static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2750 struct net_device *ndev,
2751 u8 key_index, const u8 *mac_addr,
2752 struct key_params *params
2753 )
2754#endif
2755{
2756 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2757 tCsrRoamSetKey setKey;
2758 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
2759 int status = 0;
2760 v_U32_t roamId= 0xFF;
2761 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2762 hdd_hostapd_state_t *pHostapdState;
2763 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07002764 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07002765
2766 ENTER();
2767
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002768 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2769 {
2770 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2771 "%s:LOGP in Progress. Ignore!!!", __func__);
2772 return -EAGAIN;
2773 }
2774
Jeff Johnson295189b2012-06-20 16:38:30 -07002775 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2776 __func__,pAdapter->device_mode);
2777
2778 if (CSR_MAX_NUM_KEY <= key_index)
2779 {
2780 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
2781 key_index);
2782
2783 return -EINVAL;
2784 }
2785
2786 hddLog(VOS_TRACE_LEVEL_INFO,
2787 "%s: called with key index = %d & key length %d",
2788 __func__, key_index, params->key_len);
2789
2790 /*extract key idx, key len and key*/
2791 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2792 setKey.keyId = key_index;
2793 setKey.keyLength = params->key_len;
2794 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
2795
2796 switch (params->cipher)
2797 {
2798 case WLAN_CIPHER_SUITE_WEP40:
2799 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
2800 break;
2801
2802 case WLAN_CIPHER_SUITE_WEP104:
2803 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
2804 break;
2805
2806 case WLAN_CIPHER_SUITE_TKIP:
2807 {
2808 u8 *pKey = &setKey.Key[0];
2809 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
2810
2811 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
2812
2813 /*Supplicant sends the 32bytes key in this order
2814
2815 |--------------|----------|----------|
2816 | Tk1 |TX-MIC | RX Mic |
2817 |--------------|----------|----------|
2818 <---16bytes---><--8bytes--><--8bytes-->
2819
2820 */
2821 /*Sme expects the 32 bytes key to be in the below order
2822
2823 |--------------|----------|----------|
2824 | Tk1 |RX-MIC | TX Mic |
2825 |--------------|----------|----------|
2826 <---16bytes---><--8bytes--><--8bytes-->
2827 */
2828 /* Copy the Temporal Key 1 (TK1) */
2829 vos_mem_copy(pKey, params->key,16);
2830
2831 /*Copy the rx mic first*/
2832 vos_mem_copy(&pKey[16],&params->key[24],8);
2833
2834 /*Copy the tx mic */
2835 vos_mem_copy(&pKey[24],&params->key[16],8);
2836
2837
2838 break;
2839 }
2840
2841 case WLAN_CIPHER_SUITE_CCMP:
2842 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
2843 break;
2844
2845#ifdef FEATURE_WLAN_WAPI
2846 case WLAN_CIPHER_SUITE_SMS4:
2847 {
2848 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2849 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
2850 params->key, params->key_len);
2851 return 0;
2852 }
2853#endif
2854#ifdef FEATURE_WLAN_CCX
2855 case WLAN_CIPHER_SUITE_KRK:
2856 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
2857 break;
2858#endif
2859 default:
2860 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
2861 __func__, params->cipher);
2862 return -EOPNOTSUPP;
2863 }
2864
2865 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
2866 __func__, setKey.encType);
2867
2868
2869
2870 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002871 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002872 )
2873 {
2874
2875
2876 if (
2877#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2878 (!pairwise)
2879#else
2880 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2881#endif
2882 )
2883 {
2884 /* set group key*/
2885 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson1250df42012-12-10 14:31:52 -08002886 "%s- %d: setting Broadcast key",
Jeff Johnson295189b2012-06-20 16:38:30 -07002887 __func__, __LINE__);
2888 setKey.keyDirection = eSIR_RX_ONLY;
2889 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2890 }
2891 else
2892 {
2893 /* set pairwise key*/
2894 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2895 "%s- %d: setting pairwise key",
2896 __func__, __LINE__);
2897 setKey.keyDirection = eSIR_TX_RX;
2898 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2899 }
2900
2901 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2902 if( pHostapdState->bssState == BSS_START )
2903 {
2904 status = WLANSAP_SetKeySta( pVosContext, &setKey);
2905
2906 if ( status != eHAL_STATUS_SUCCESS )
2907 {
2908 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2909 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
2910 __LINE__, status );
2911 }
2912 }
2913
2914 /* Saving WEP keys */
2915 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
2916 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
2917 {
2918 //Save the wep key in ap context. Issue setkey after the BSS is started.
2919 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2920 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
2921 }
2922 else
2923 {
2924 //Save the key in ap context. Issue setkey after the BSS is started.
2925 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2926 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
2927 }
2928 }
2929 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07002930 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07002931 )
2932 {
2933 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2934 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2935
2936 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
2937
Venkata Prathyusha Kuntupalliee2ce712013-01-17 14:09:24 -08002938 pWextState->roamProfile.Keys.defaultIndex = key_index;
2939
2940
Jeff Johnson295189b2012-06-20 16:38:30 -07002941 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
2942 params->key, params->key_len);
2943
2944 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
2945
2946 if (!( ( IW_AUTH_KEY_MGMT_802_1X
2947 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2948 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2949 )
2950 &&
2951 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
2952 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
2953 )
2954 )
2955 {
2956 /* in case of static WEP, macaddr/bssid is not coming from nl80211
2957 * interface, copy bssid for pairwise key and group macaddr for
2958 * group key initialization*/
2959
2960 tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
2961
2962 pWextState->roamProfile.negotiatedUCEncryptionType =
2963 pHddStaCtx->conn_info.ucEncryptionType =
2964 ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
2965 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
2966 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
2967
2968
2969 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2970 "%s: Negotiated encryption type %d", __func__,
2971 pWextState->roamProfile.negotiatedUCEncryptionType);
2972
2973 sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
2974 &pWextState->roamProfile, true);
2975 setKey.keyLength = 0;
2976 setKey.keyDirection = eSIR_TX_RX;
2977
2978#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2979 if (pairwise)
2980 {
2981#endif
2982 if (mac_addr)
2983 {
2984 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2985 }
2986 else
2987 {
2988 /* macaddr is NULL, set the peerMac to bssId in case of BSS,
2989 * and peerMacAddress in case of IBSS*/
2990 if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
2991 {
2992 u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
2993 if (HDD_MAX_NUM_IBSS_STA != staidx)
2994 {
2995 vos_mem_copy(setKey.peerMac,
2996 &pHddStaCtx->conn_info.peerMacAddress[staidx],
2997 WNI_CFG_BSSID_LEN);
2998
2999 }
3000 else
3001 {
3002 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
3003 __func__);
3004 return -EOPNOTSUPP;
3005 }
3006 }
3007 else
3008 {
3009 vos_mem_copy(setKey.peerMac,
3010 &pHddStaCtx->conn_info.bssId[0],
3011 WNI_CFG_BSSID_LEN);
3012 }
3013 }
3014#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3015 }
3016 else
3017 {
3018 /* set group key*/
3019 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3020 "%s- %d: setting Group key",
3021 __func__, __LINE__);
3022 setKey.keyDirection = eSIR_RX_ONLY;
3023 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3024 }
3025#endif
3026 }
3027 else if (
3028#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3029 (!pairwise)
3030#else
3031 (!mac_addr || is_broadcast_ether_addr(mac_addr))
3032#endif
3033 )
3034 {
3035 /* set group key*/
3036 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3037 "%s- %d: setting Group key",
3038 __func__, __LINE__);
3039 setKey.keyDirection = eSIR_RX_ONLY;
3040 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3041 }
3042 else
3043 {
3044 /* set pairwise key*/
3045 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3046 "%s- %d: setting pairwise key",
3047 __func__, __LINE__);
3048 setKey.keyDirection = eSIR_TX_RX;
3049 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3050 }
3051
3052 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3053 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3054 __func__, setKey.peerMac[0], setKey.peerMac[1],
3055 setKey.peerMac[2], setKey.peerMac[3],
3056 setKey.peerMac[4], setKey.peerMac[5],
3057 setKey.keyDirection);
3058
3059 vos_status = wlan_hdd_check_ula_done(pAdapter);
3060
3061 if ( vos_status != VOS_STATUS_SUCCESS )
3062 {
3063 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3064 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
3065 __LINE__, vos_status );
3066
3067 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3068
3069 return -EINVAL;
3070
3071 }
3072
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003073#ifdef WLAN_FEATURE_VOWIFI_11R
3074 /* The supplicant may attempt to set the PTK once pre-authentication is done.
3075 Save the key in the UMAC and include it in the ADD BSS request */
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003076 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303077 if( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_WAIT )
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003078 {
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303079 return -EINVAL;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003080 }
3081#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07003082
3083 /* issue set key request to SME*/
3084 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3085 pAdapter->sessionId, &setKey, &roamId );
3086
3087 if ( 0 != status )
3088 {
3089 hddLog(VOS_TRACE_LEVEL_ERROR,
3090 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3091 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3092 return -EINVAL;
3093 }
3094
3095
3096 /* in case of IBSS as there was no information available about WEP keys during
3097 * IBSS join, group key intialized with NULL key, so re-initialize group key
3098 * with correct value*/
3099 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
3100 !( ( IW_AUTH_KEY_MGMT_802_1X
3101 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
3102 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3103 )
3104 &&
3105 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3106 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3107 )
3108 )
3109 {
3110 setKey.keyDirection = eSIR_RX_ONLY;
3111 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3112
3113 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3114 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3115 __func__, setKey.peerMac[0], setKey.peerMac[1],
3116 setKey.peerMac[2], setKey.peerMac[3],
3117 setKey.peerMac[4], setKey.peerMac[5],
3118 setKey.keyDirection);
3119
3120 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3121 pAdapter->sessionId, &setKey, &roamId );
3122
3123 if ( 0 != status )
3124 {
3125 hddLog(VOS_TRACE_LEVEL_ERROR,
3126 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
3127 __func__, status);
3128 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3129 return -EINVAL;
3130 }
3131 }
3132 }
3133
3134 return 0;
3135}
3136
3137/*
3138 * FUNCTION: wlan_hdd_cfg80211_get_key
3139 * This function is used to get the key information
3140 */
3141#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3142static int wlan_hdd_cfg80211_get_key(
3143 struct wiphy *wiphy,
3144 struct net_device *ndev,
3145 u8 key_index, bool pairwise,
3146 const u8 *mac_addr, void *cookie,
3147 void (*callback)(void *cookie, struct key_params*)
3148 )
3149#else
3150static int wlan_hdd_cfg80211_get_key(
3151 struct wiphy *wiphy,
3152 struct net_device *ndev,
3153 u8 key_index, const u8 *mac_addr, void *cookie,
3154 void (*callback)(void *cookie, struct key_params*)
3155 )
3156#endif
3157{
3158 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3159 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3160 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
3161 struct key_params params;
3162
3163 ENTER();
3164
3165 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3166 __func__,pAdapter->device_mode);
3167
3168 memset(&params, 0, sizeof(params));
3169
3170 if (CSR_MAX_NUM_KEY <= key_index)
3171 {
3172 return -EINVAL;
3173 }
3174
3175 switch(pRoamProfile->EncryptionType.encryptionType[0])
3176 {
3177 case eCSR_ENCRYPT_TYPE_NONE:
3178 params.cipher = IW_AUTH_CIPHER_NONE;
3179 break;
3180
3181 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3182 case eCSR_ENCRYPT_TYPE_WEP40:
3183 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3184 break;
3185
3186 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3187 case eCSR_ENCRYPT_TYPE_WEP104:
3188 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3189 break;
3190
3191 case eCSR_ENCRYPT_TYPE_TKIP:
3192 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3193 break;
3194
3195 case eCSR_ENCRYPT_TYPE_AES:
3196 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3197 break;
3198
3199 default:
3200 params.cipher = IW_AUTH_CIPHER_NONE;
3201 break;
3202 }
3203
3204 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3205 params.seq_len = 0;
3206 params.seq = NULL;
3207 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3208 callback(cookie, &params);
3209 return 0;
3210}
3211
3212/*
3213 * FUNCTION: wlan_hdd_cfg80211_del_key
3214 * This function is used to delete the key information
3215 */
3216#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3217static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3218 struct net_device *ndev,
3219 u8 key_index,
3220 bool pairwise,
3221 const u8 *mac_addr
3222 )
3223#else
3224static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3225 struct net_device *ndev,
3226 u8 key_index,
3227 const u8 *mac_addr
3228 )
3229#endif
3230{
3231 int status = 0;
3232
3233 //This code needs to be revisited. There is sme_removeKey API, we should
3234 //plan to use that. After the change to use correct index in setkey,
3235 //it is observed that this is invalidating peer
3236 //key index whenever re-key is done. This is affecting data link.
3237 //It should be ok to ignore del_key.
3238#if 0
3239 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3240 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
3241 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3242 tCsrRoamSetKey setKey;
3243 v_U32_t roamId= 0xFF;
3244
3245 ENTER();
3246
3247 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3248 __func__,pAdapter->device_mode);
3249
3250 if (CSR_MAX_NUM_KEY <= key_index)
3251 {
3252 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3253 key_index);
3254
3255 return -EINVAL;
3256 }
3257
3258 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3259 setKey.keyId = key_index;
3260
3261 if (mac_addr)
3262 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3263 else
3264 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3265
3266 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3267
3268 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003269 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07003270 )
3271 {
3272
3273 hdd_hostapd_state_t *pHostapdState =
3274 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3275 if( pHostapdState->bssState == BSS_START)
3276 {
3277 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3278
3279 if ( status != eHAL_STATUS_SUCCESS )
3280 {
3281 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3282 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3283 __LINE__, status );
3284 }
3285 }
3286 }
3287 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003288 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003289 )
3290 {
3291 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3292
3293 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3294
3295 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3296 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
3297 __func__, setKey.peerMac[0], setKey.peerMac[1],
3298 setKey.peerMac[2], setKey.peerMac[3],
3299 setKey.peerMac[4], setKey.peerMac[5]);
3300 if(pAdapter->sessionCtx.station.conn_info.connState ==
3301 eConnectionState_Associated)
3302 {
3303 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3304 pAdapter->sessionId, &setKey, &roamId );
3305
3306 if ( 0 != status )
3307 {
3308 hddLog(VOS_TRACE_LEVEL_ERROR,
3309 "%s: sme_RoamSetKey failure, returned %d",
3310 __func__, status);
3311 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3312 return -EINVAL;
3313 }
3314 }
3315 }
3316#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003317 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003318 return status;
3319}
3320
3321/*
3322 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3323 * This function is used to set the default tx key index
3324 */
3325#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3326static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3327 struct net_device *ndev,
3328 u8 key_index,
3329 bool unicast, bool multicast)
3330#else
3331static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3332 struct net_device *ndev,
3333 u8 key_index)
3334#endif
3335{
3336 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3337 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3338 int status = 0;
3339 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3340
3341 ENTER();
3342
3343 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3344 __func__,pAdapter->device_mode, key_index);
3345
3346 if (CSR_MAX_NUM_KEY <= key_index)
3347 {
3348 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3349 key_index);
3350
3351 return -EINVAL;
3352 }
3353
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003354 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3355 {
3356 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3357 "%s:LOGP in Progress. Ignore!!!", __func__);
3358 return -EAGAIN;
3359 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003360
3361 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003362 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003363 )
3364 {
3365 if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
3366 (eCSR_ENCRYPT_TYPE_TKIP !=
3367 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3368 (eCSR_ENCRYPT_TYPE_AES !=
3369 pWextState->roamProfile.EncryptionType.encryptionType[0])
3370 )
3371 {
3372 /* if default key index is not same as previous one,
3373 * then update the default key index */
3374
3375 tCsrRoamSetKey setKey;
3376 v_U32_t roamId= 0xFF;
3377 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
3378
3379 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
3380 __func__, key_index);
3381
3382 Keys->defaultIndex = (u8)key_index;
3383 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3384 setKey.keyId = key_index;
3385 setKey.keyLength = Keys->KeyLength[key_index];
3386
3387 vos_mem_copy(&setKey.Key[0],
3388 &Keys->KeyMaterial[key_index][0],
3389 Keys->KeyLength[key_index]);
3390
3391 setKey.keyDirection = eSIR_TX_ONLY;
3392
3393 vos_mem_copy(setKey.peerMac,
3394 &pHddStaCtx->conn_info.bssId[0],
3395 WNI_CFG_BSSID_LEN);
3396
3397 setKey.encType =
3398 pWextState->roamProfile.EncryptionType.encryptionType[0];
3399
3400 /* issue set key request */
3401 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3402 pAdapter->sessionId, &setKey, &roamId );
3403
3404 if ( 0 != status )
3405 {
3406 hddLog(VOS_TRACE_LEVEL_ERROR,
3407 "%s: sme_RoamSetKey failed, returned %d", __func__,
3408 status);
3409 return -EINVAL;
3410 }
3411 }
3412 }
3413
3414 /* In SoftAp mode setting key direction for default mode */
3415 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3416 {
3417 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3418 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3419 (eCSR_ENCRYPT_TYPE_AES !=
3420 pWextState->roamProfile.EncryptionType.encryptionType[0])
3421 )
3422 {
3423 /* Saving key direction for default key index to TX default */
3424 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3425 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3426 }
3427 }
3428
3429 return status;
3430}
3431
Jeff Johnson295189b2012-06-20 16:38:30 -07003432/*
3433 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3434 * This function is used to inform the BSS details to nl80211 interface.
3435 */
3436static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3437 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3438{
3439 struct net_device *dev = pAdapter->dev;
3440 struct wireless_dev *wdev = dev->ieee80211_ptr;
3441 struct wiphy *wiphy = wdev->wiphy;
3442 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3443 int chan_no;
3444 int ie_length;
3445 const char *ie;
3446 unsigned int freq;
3447 struct ieee80211_channel *chan;
3448 int rssi = 0;
3449 struct cfg80211_bss *bss = NULL;
3450
3451 ENTER();
3452
3453 if( NULL == pBssDesc )
3454 {
3455 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3456 return bss;
3457 }
3458
3459 chan_no = pBssDesc->channelId;
3460 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3461 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3462
3463 if( NULL == ie )
3464 {
3465 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3466 return bss;
3467 }
3468
3469#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3470 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3471 {
3472 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3473 }
3474 else
3475 {
3476 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3477 }
3478#else
3479 freq = ieee80211_channel_to_frequency(chan_no);
3480#endif
3481
3482 chan = __ieee80211_get_channel(wiphy, freq);
3483
3484 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3485 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3486 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3487 if (bss == NULL)
3488 {
3489 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3490
3491 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3492 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3493 pBssDesc->capabilityInfo,
3494 pBssDesc->beaconInterval, ie, ie_length,
3495 rssi, GFP_KERNEL ));
3496}
3497 else
3498 {
3499 return bss;
3500 }
3501}
3502
3503
3504
3505/*
3506 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3507 * This function is used to inform the BSS details to nl80211 interface.
3508 */
3509struct cfg80211_bss*
3510wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3511 tSirBssDescription *bss_desc
3512 )
3513{
3514 /*
3515 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3516 already exists in bss data base of cfg80211 for that particular BSS ID.
3517 Using cfg80211_inform_bss_frame to update the bss entry instead of
3518 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3519 now there is no possibility to get the mgmt(probe response) frame from PE,
3520 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3521 cfg80211_inform_bss_frame.
3522 */
3523 struct net_device *dev = pAdapter->dev;
3524 struct wireless_dev *wdev = dev->ieee80211_ptr;
3525 struct wiphy *wiphy = wdev->wiphy;
3526 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003527#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3528 qcom_ie_age *qie_age = NULL;
3529 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3530#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003531 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003532#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003533 const char *ie =
3534 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3535 unsigned int freq;
3536 struct ieee80211_channel *chan;
3537 struct ieee80211_mgmt *mgmt =
3538 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3539 struct cfg80211_bss *bss_status = NULL;
3540 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3541 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003542#ifdef WLAN_OPEN_SOURCE
3543 struct timespec ts;
3544#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003545
3546 ENTER();
3547
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003548 if (!mgmt)
3549 return NULL;
3550
Jeff Johnson295189b2012-06-20 16:38:30 -07003551 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003552
3553#ifdef WLAN_OPEN_SOURCE
3554 /* Android does not want the timestamp from the frame.
3555 Instead it wants a monotonic increasing value */
3556 get_monotonic_boottime(&ts);
3557 mgmt->u.probe_resp.timestamp =
3558 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3559#else
3560 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003561 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3562 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003563
3564#endif
3565
Jeff Johnson295189b2012-06-20 16:38:30 -07003566 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3567 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003568
3569#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3570 /* GPS Requirement: need age ie per entry. Using vendor specific. */
3571 /* Assuming this is the last IE, copy at the end */
3572 ie_length -=sizeof(qcom_ie_age);
3573 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
3574 qie_age->element_id = QCOM_VENDOR_IE_ID;
3575 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
3576 qie_age->oui_1 = QCOM_OUI1;
3577 qie_age->oui_2 = QCOM_OUI2;
3578 qie_age->oui_3 = QCOM_OUI3;
3579 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
3580 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
3581#endif
3582
Jeff Johnson295189b2012-06-20 16:38:30 -07003583 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3584
3585 mgmt->frame_control |=
3586 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3587
3588#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3589 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3590 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3591 {
3592 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3593 }
3594 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3595 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3596
3597 {
3598 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3599 }
3600 else
3601 {
3602 kfree(mgmt);
3603 return NULL;
3604 }
3605#else
3606 freq = ieee80211_channel_to_frequency(chan_no);
3607#endif
3608 chan = __ieee80211_get_channel(wiphy, freq);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08003609 /*when the band is changed on the fly using the GUI, three things are done
3610 * 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)
3611 * as part of the scan abort, message willbe queued to PE and we proceed with flushing and changinh the band.
3612 * pe will stop the scanning further and report back the results what ever it had till now by calling the call back function.
3613 * if the time between update band and scandone call back is sufficent enough the band change reflects in SME, SME validates the channels
3614 * and discards the channels correponding to previous band and calls back with zero bss results.
3615 * 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
3616 * all the channels correponding to previous band.this is due to race condition.but those channels are invalid to the new band and so
3617 * this function __ieee80211_get_channel will return NULL.Each time we report scan result with this pointer null warning kernel trace is printed.
3618 * if the scan results contain large number of APs continuosly kernel warning trace is printed and it will lead to apps watch dog bark.
3619 * So drop the bss and continue to next bss.
3620 */
3621 if(chan == NULL)
3622 {
3623 hddLog(VOS_TRACE_LEVEL_INFO, "%s chan pointer is NULL", __func__);
3624 return NULL;
3625 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003626 /*To keep the rssi icon of the connected AP in the scan window
3627 *and the rssi icon of the wireless networks in sync
3628 * */
3629 if (( eConnectionState_Associated ==
3630 pAdapter->sessionCtx.station.conn_info.connState ) &&
3631 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3632 pAdapter->sessionCtx.station.conn_info.bssId,
3633 WNI_CFG_BSSID_LEN)))
3634 {
3635 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3636 rssi = (pAdapter->rssi * 100);
3637 }
3638 else
3639 {
3640 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3641 }
3642
3643 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3644 frame_len, rssi, GFP_KERNEL);
3645 kfree(mgmt);
3646 return bss_status;
3647}
3648
3649/*
3650 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3651 * This function is used to update the BSS data base of CFG8011
3652 */
3653struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3654 tCsrRoamInfo *pRoamInfo
3655 )
3656{
3657 tCsrRoamConnectedProfile roamProfile;
3658 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3659 struct cfg80211_bss *bss = NULL;
3660
3661 ENTER();
3662
3663 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
3664 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
3665
3666 if (NULL != roamProfile.pBssDesc)
3667 {
3668 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
3669 &roamProfile);
3670
3671 if (NULL == bss)
3672 {
3673 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
3674 __func__);
3675 }
3676
3677 sme_RoamFreeConnectProfile(hHal, &roamProfile);
3678 }
3679 else
3680 {
3681 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
3682 __func__);
3683 }
3684 return bss;
3685}
3686
3687/*
3688 * FUNCTION: wlan_hdd_cfg80211_update_bss
3689 */
3690static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
3691 hdd_adapter_t *pAdapter
3692 )
3693{
3694 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3695 tCsrScanResultInfo *pScanResult;
3696 eHalStatus status = 0;
3697 tScanResultHandle pResult;
3698 struct cfg80211_bss *bss_status = NULL;
3699
3700 ENTER();
3701
3702 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3703 {
3704 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3705 return -EAGAIN;
3706 }
3707
3708 /*
3709 * start getting scan results and populate cgf80211 BSS database
3710 */
3711 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
3712
3713 /* no scan results */
3714 if (NULL == pResult)
3715 {
3716 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
3717 return status;
3718 }
3719
3720 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
3721
3722 while (pScanResult)
3723 {
3724 /*
3725 * cfg80211_inform_bss() is not updating ie field of bss entry, if
3726 * entry already exists in bss data base of cfg80211 for that
3727 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
3728 * bss entry instead of cfg80211_inform_bss, But this call expects
3729 * mgmt packet as input. As of now there is no possibility to get
3730 * the mgmt(probe response) frame from PE, converting bss_desc to
3731 * ieee80211_mgmt(probe response) and passing to c
3732 * fg80211_inform_bss_frame.
3733 * */
3734
3735 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
3736 &pScanResult->BssDescriptor);
3737
3738
3739 if (NULL == bss_status)
3740 {
3741 hddLog(VOS_TRACE_LEVEL_INFO,
3742 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
3743 }
3744 else
3745 {
3746 cfg80211_put_bss(bss_status);
3747 }
3748
3749 pScanResult = sme_ScanResultGetNext(hHal, pResult);
3750 }
3751
3752 sme_ScanResultPurge(hHal, pResult);
3753
3754 return 0;
3755}
3756
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003757void
3758hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
3759{
3760 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003761 "%02X:%02X:%02X:%02X:%02X:%02X\n",
3762 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
3763 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003764} /****** end hddPrintMacAddr() ******/
3765
3766void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003767hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003768{
3769 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003770 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
3771 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
3772 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
3773 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003774} /****** end hddPrintPmkId() ******/
3775
3776//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
3777//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
3778
3779//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
3780//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
3781
3782#define dump_bssid(bssid) \
3783 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003784 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
3785 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
3786 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003787 }
3788
3789#define dump_pmkid(pMac, pmkid) \
3790 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003791 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
3792 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
3793 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003794 }
3795
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07003796#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003797/*
3798 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
3799 * This function is used to notify the supplicant of a new PMKSA candidate.
3800 */
3801int wlan_hdd_cfg80211_pmksa_candidate_notify(
3802 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
3803 int index, bool preauth )
3804{
Jeff Johnsone7245742012-09-05 17:12:55 -07003805#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003806 struct net_device *dev = pAdapter->dev;
3807
3808 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07003809 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003810
3811 if( NULL == pRoamInfo )
3812 {
3813 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
3814 return -EINVAL;
3815 }
3816
3817 dump_bssid(pRoamInfo->bssid);
3818 cfg80211_pmksa_candidate_notify(dev, index,
3819 pRoamInfo->bssid, preauth, GFP_KERNEL);
Jeff Johnsone7245742012-09-05 17:12:55 -07003820#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003821 return 0;
3822}
3823#endif //FEATURE_WLAN_LFR
3824
Jeff Johnson295189b2012-06-20 16:38:30 -07003825/*
3826 * FUNCTION: hdd_cfg80211_scan_done_callback
3827 * scanning callback function, called after finishing scan
3828 *
3829 */
3830static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
3831 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
3832{
3833 struct net_device *dev = (struct net_device *) pContext;
3834 //struct wireless_dev *wdev = dev->ieee80211_ptr;
3835 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003836 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3837 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07003838 struct cfg80211_scan_request *req = NULL;
3839 int ret = 0;
3840
3841 ENTER();
3842
3843 hddLog(VOS_TRACE_LEVEL_INFO,
3844 "%s called with halHandle = %p, pContext = %p,"
3845 "scanID = %d, returned status = %d\n",
3846 __func__, halHandle, pContext, (int) scanId, (int) status);
3847
3848 //Block on scan req completion variable. Can't wait forever though.
3849 ret = wait_for_completion_interruptible_timeout(
3850 &pScanInfo->scan_req_completion_event,
3851 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
3852 if (!ret)
3853 {
3854 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003855 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003856 }
3857
3858 if(pScanInfo->mScanPending != VOS_TRUE)
3859 {
3860 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003861 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003862 }
3863
3864 /* Check the scanId */
3865 if (pScanInfo->scanId != scanId)
3866 {
3867 hddLog(VOS_TRACE_LEVEL_INFO,
3868 "%s called with mismatched scanId pScanInfo->scanId = %d "
3869 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
3870 (int) scanId);
3871 }
3872
Jeff Johnson295189b2012-06-20 16:38:30 -07003873 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
3874 pAdapter);
3875
3876 if (0 > ret)
3877 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
3878
3879
3880 /* If any client wait scan result through WEXT
3881 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003882 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07003883 {
3884 /* The other scan request waiting for current scan finish
3885 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003886 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003887 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003888 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003889 }
3890 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003891 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003892 {
3893 struct net_device *dev = pAdapter->dev;
3894 union iwreq_data wrqu;
3895 int we_event;
3896 char *msg;
3897
3898 memset(&wrqu, '\0', sizeof(wrqu));
3899 we_event = SIOCGIWSCAN;
3900 msg = NULL;
3901 wireless_send_event(dev, we_event, &wrqu, msg);
3902 }
3903 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003904 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003905
3906 /* Get the Scan Req */
3907 req = pAdapter->request;
3908
3909 if (!req)
3910 {
3911 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003912 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07003913 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003914 }
3915
3916 /*
3917 * setting up 0, just in case.
3918 */
3919 req->n_ssids = 0;
3920 req->n_channels = 0;
3921 req->ie = 0;
3922
Jeff Johnson295189b2012-06-20 16:38:30 -07003923 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003924 /* Scan is no longer pending */
3925 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003926
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07003927 /*
3928 * cfg80211_scan_done informing NL80211 about completion
3929 * of scanning
3930 */
3931 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08003932 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003933
Jeff Johnsone7245742012-09-05 17:12:55 -07003934allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003935 /* release the wake lock at the end of the scan*/
3936 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07003937
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003938 /* Acquire wakelock to handle the case where APP's tries to suspend
3939 * immediatly after the driver gets connect request(i.e after scan)
3940 * from supplicant, this result in app's is suspending and not able
3941 * to process the connect request to AP */
3942 hdd_allow_suspend_timeout(100);
3943
Jeff Johnson295189b2012-06-20 16:38:30 -07003944 EXIT();
3945 return 0;
3946}
3947
3948/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08003949 * FUNCTION: hdd_isScanAllowed
3950 * Go through each adapter and check if scan allowed
3951 *
3952 */
3953v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
3954{
3955 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3956 hdd_station_ctx_t *pHddStaCtx = NULL;
3957 hdd_adapter_t *pAdapter = NULL;
3958 VOS_STATUS status = 0;
3959 v_U8_t staId = 0;
3960 v_U8_t *staMac = NULL;
3961
3962 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3963
3964 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3965 {
3966 pAdapter = pAdapterNode->pAdapter;
3967
3968 if( pAdapter )
3969 {
3970 hddLog(VOS_TRACE_LEVEL_INFO,
3971 "%s: Adapter with device mode %d exists",
3972 __func__, pAdapter->device_mode);
3973 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3974 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
3975 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
3976 {
3977 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3978 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
3979 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
3980 {
3981 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
3982 hddLog(VOS_TRACE_LEVEL_ERROR,
3983 "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the "
3984 "middle of WPS/EAPOL exchange.", __func__,
3985 staMac[0], staMac[1], staMac[2],
3986 staMac[3], staMac[4], staMac[5]);
3987 return VOS_FALSE;
3988 }
3989 }
3990 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
3991 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
3992 {
3993 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
3994 {
3995 if ((pAdapter->aStaInfo[staId].isUsed) &&
3996 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
3997 {
3998 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
3999
4000 hddLog(VOS_TRACE_LEVEL_ERROR,
4001 "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the "
4002 "middle of WPS/EAPOL exchange.", __func__,
4003 staMac[0], staMac[1], staMac[2],
4004 staMac[3], staMac[4], staMac[5]);
4005 return VOS_FALSE;
4006 }
4007 }
4008 }
4009 }
4010 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4011 pAdapterNode = pNext;
4012 }
4013 hddLog(VOS_TRACE_LEVEL_INFO,
4014 "%s: Scan allowed", __func__);
4015 return VOS_TRUE;
4016}
4017
4018/*
Jeff Johnson295189b2012-06-20 16:38:30 -07004019 * FUNCTION: wlan_hdd_cfg80211_scan
4020 * this scan respond to scan trigger and update cfg80211 scan database
4021 * later, scan dump command can be used to recieve scan results
4022 */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08004023int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
4024#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4025 struct net_device *dev,
4026#endif
4027 struct cfg80211_scan_request *request)
4028{
4029#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4030 struct net_device *dev = request->wdev->netdev;
4031#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004032 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4033 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4034 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4035 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
4036 tCsrScanRequest scanRequest;
4037 tANI_U8 *channelList = NULL, i;
4038 v_U32_t scanId = 0;
4039 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004040 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004041 v_U8_t* pP2pIe = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004042
4043 ENTER();
4044
4045 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4046 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004047
4048 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
4049 (eConnectionState_Connecting ==
4050 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) )
4051 {
4052 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004053 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
4054 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004055 return -EBUSY;
4056 }
4057
Jeff Johnson295189b2012-06-20 16:38:30 -07004058#ifdef WLAN_BTAMP_FEATURE
4059 //Scan not supported when AMP traffic is on.
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004060 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
Jeff Johnson295189b2012-06-20 16:38:30 -07004061 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004062 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004063 "%s: No scanning when AMP is on", __func__);
4064 return -EOPNOTSUPP;
4065 }
4066#endif
4067 //Scan on any other interface is not supported.
4068 if( pAdapter->device_mode == WLAN_HDD_SOFTAP )
4069 {
4070 hddLog(VOS_TRACE_LEVEL_ERROR,
4071 "%s: Not scanning on device_mode = %d",
4072 __func__, pAdapter->device_mode);
4073 return -EOPNOTSUPP;
4074 }
4075
4076 if (TRUE == pScanInfo->mScanPending)
4077 {
4078 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
4079 return -EBUSY;
4080 }
4081
4082 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4083 {
4084 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4085 "%s:LOGP in Progress. Ignore!!!", __func__);
4086 return -EAGAIN;
4087 }
4088
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07004089 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
4090 {
4091 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4092 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
4093 return -EAGAIN;
4094 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004095 //Don't Allow Scan and return busy if Remain On
4096 //Channel and action frame is pending
4097 //Otherwise Cancel Remain On Channel and allow Scan
4098 //If no action frame pending
4099 if(0 != wlan_hdd_check_remain_on_channel(pAdapter))
4100 {
4101 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
4102 return -EBUSY;
4103 }
4104
Jeff Johnson295189b2012-06-20 16:38:30 -07004105 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
4106 {
4107 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08004108 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004109 return -EAGAIN;
4110 }
4111 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
4112 {
4113 hddLog(VOS_TRACE_LEVEL_WARN,
4114 "%s: MAX TM Level Scan not allowed", __func__);
4115 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4116 return -EBUSY;
4117 }
4118 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4119
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004120 /* Check if scan is allowed at this point of time.
4121 */
4122 if (!hdd_isScanAllowed(pHddCtx))
4123 {
4124 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
4125 return -EBUSY;
4126 }
4127
Jeff Johnson295189b2012-06-20 16:38:30 -07004128 vos_mem_zero( &scanRequest, sizeof(scanRequest));
4129
4130 if (NULL != request)
4131 {
4132 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
4133 (int)request->n_ssids);
4134
4135 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
4136 * Becasue of this, driver is assuming that this is not wildcard scan and so
4137 * is not aging out the scan results.
4138 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07004139 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07004140 {
4141 request->n_ssids = 0;
4142 }
4143
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004144 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07004145 {
4146 tCsrSSIDInfo *SsidInfo;
4147 int j;
4148 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
4149 /* Allocate num_ssid tCsrSSIDInfo structure */
4150 SsidInfo = scanRequest.SSIDs.SSIDList =
4151 ( tCsrSSIDInfo *)vos_mem_malloc(
4152 request->n_ssids*sizeof(tCsrSSIDInfo));
4153
4154 if(NULL == scanRequest.SSIDs.SSIDList)
4155 {
4156 hddLog(VOS_TRACE_LEVEL_ERROR,
4157 "memory alloc failed SSIDInfo buffer");
4158 return -ENOMEM;
4159 }
4160
4161 /* copy all the ssid's and their length */
4162 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
4163 {
4164 /* get the ssid length */
4165 SsidInfo->SSID.length = request->ssids[j].ssid_len;
4166 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
4167 SsidInfo->SSID.length);
4168 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
4169 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
4170 j, SsidInfo->SSID.ssId);
4171 }
4172 /* set the scan type to active */
4173 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4174 }
4175 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4176 {
4177 /* set the scan type to active */
4178 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4179 }
4180 else
4181 {
4182 /*Set the scan type to default type, in this case it is ACTIVE*/
4183 scanRequest.scanType = pScanInfo->scan_mode;
4184 }
4185 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
4186 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4187 }
4188 else
4189 {
4190 /* set the scan type to active */
4191 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4192 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4193
4194 /* set min and max channel time to zero */
4195 scanRequest.minChnTime = 0;
4196 scanRequest.maxChnTime = 0;
4197 }
4198
4199 /* set BSSType to default type */
4200 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4201
4202 /*TODO: scan the requested channels only*/
4203
4204 /*Right now scanning all the channels */
4205 if( request )
4206 {
4207 if( request->n_channels )
4208 {
4209 channelList = vos_mem_malloc( request->n_channels );
4210 if( NULL == channelList )
4211 {
4212 status = -ENOMEM;
4213 goto free_mem;
4214 }
4215
4216 for( i = 0 ; i < request->n_channels ; i++ )
4217 channelList[i] = request->channels[i]->hw_value;
4218 }
4219
4220 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4221 scanRequest.ChannelInfo.ChannelList = channelList;
4222
4223 /* set requestType to full scan */
4224 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004225
4226 /* Flush the scan results(only p2p beacons) for STA scan and P2P
4227 * search (Flush on both full scan and social scan but not on single
4228 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
4229 */
4230
4231 /* Supplicant does single channel scan after 8-way handshake
4232 * and in that case driver shoudnt flush scan results. If
4233 * driver flushes the scan results here and unfortunately if
4234 * the AP doesnt respond to our probe req then association
4235 * fails which is not desired
4236 */
4237
4238 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4239 {
4240 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4241 pAdapter->sessionId );
4242 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004243
4244 if( request->ie_len )
4245 {
4246 /* save this for future association (join requires this) */
4247 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4248 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4249 pScanInfo->scanAddIE.length = request->ie_len;
4250
4251 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004252 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4253 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004254 )
4255 {
4256 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4257 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4258 }
4259
4260 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4261 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4262
Jeff Johnson295189b2012-06-20 16:38:30 -07004263 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4264 request->ie_len);
4265 if (pP2pIe != NULL)
4266 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004267#ifdef WLAN_FEATURE_P2P_DEBUG
4268 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4269 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4270 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4271 {
4272 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4273 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4274 "Go nego completed to Connection is started");
4275 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4276 "for 8way Handshake");
4277 }
4278 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4279 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4280 {
4281 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4282 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4283 "Disconnected state to Connection is started");
4284 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4285 "for 4way Handshake");
4286 }
4287#endif
4288
Jeff Johnsone7245742012-09-05 17:12:55 -07004289 /* no_cck will be set during p2p find to disable 11b rates */
4290 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004291 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004292 hddLog(VOS_TRACE_LEVEL_INFO,
4293 "%s: This is a P2P Search", __func__);
4294 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004295
Jeff Johnsone7245742012-09-05 17:12:55 -07004296 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4297 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004298 /* set requestType to P2P Discovery */
4299 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004300 }
4301
4302 /*
4303 Skip Dfs Channel in case of P2P Search
4304 if it is set in ini file
4305 */
4306 if(cfg_param->skipDfsChnlInP2pSearch)
4307 {
4308 scanRequest.skipDfsChnlInP2pSearch = 1;
4309 }
4310 else
4311 {
4312 scanRequest.skipDfsChnlInP2pSearch = 0;
4313 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004314
Jeff Johnson295189b2012-06-20 16:38:30 -07004315 }
4316 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004317 }
4318 }
4319
4320 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4321
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004322 /* acquire the wakelock to avoid the apps suspend during the scan. To
4323 * address the following issues.
4324 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4325 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4326 * for long time, this result in apps running at full power for long time.
4327 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4328 * be stuck in full power because of resume BMPS
4329 */
4330 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004331
4332 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004333 pAdapter->sessionId, &scanRequest, &scanId,
4334 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004335
Jeff Johnson295189b2012-06-20 16:38:30 -07004336 if (eHAL_STATUS_SUCCESS != status)
4337 {
4338 hddLog(VOS_TRACE_LEVEL_ERROR,
4339 "%s: sme_ScanRequest returned error %d", __func__, status);
4340 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004341 if(eHAL_STATUS_RESOURCES == status)
4342 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004343 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 -07004344 status = -EBUSY;
4345 } else {
4346 status = -EIO;
4347 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004348 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004349 goto free_mem;
4350 }
4351
4352 pScanInfo->mScanPending = TRUE;
4353 pAdapter->request = request;
4354 pScanInfo->scanId = scanId;
4355
4356 complete(&pScanInfo->scan_req_completion_event);
4357
4358free_mem:
4359 if( scanRequest.SSIDs.SSIDList )
4360 {
4361 vos_mem_free(scanRequest.SSIDs.SSIDList);
4362 }
4363
4364 if( channelList )
4365 vos_mem_free( channelList );
4366
4367 EXIT();
4368
4369 return status;
4370}
4371
4372/*
4373 * FUNCTION: wlan_hdd_cfg80211_connect_start
4374 * This function is used to start the association process
4375 */
4376int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004377 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004378{
4379 int status = 0;
4380 hdd_wext_state_t *pWextState;
4381 v_U32_t roamId;
4382 tCsrRoamProfile *pRoamProfile;
4383 eMib_dot11DesiredBssType connectedBssType;
4384 eCsrAuthType RSNAuthType;
4385
4386 ENTER();
4387
4388 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4389
4390 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4391 {
4392 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4393 return -EINVAL;
4394 }
4395
4396 pRoamProfile = &pWextState->roamProfile;
4397
4398 if (pRoamProfile)
4399 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004400 int ret = 0;
4401 hdd_station_ctx_t *pHddStaCtx;
4402 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4403 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4404
4405 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4406 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4407 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004408 {
4409 /* Issue disconnect to CSR */
4410 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4411 if( eHAL_STATUS_SUCCESS ==
4412 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4413 pAdapter->sessionId,
4414 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4415 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004416 ret = wait_for_completion_interruptible_timeout(
4417 &pAdapter->disconnect_comp_var,
4418 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4419 if (0 == ret)
4420 {
4421 VOS_ASSERT(0);
4422 }
4423 }
4424 }
4425 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4426 {
4427 ret = wait_for_completion_interruptible_timeout(
4428 &pAdapter->disconnect_comp_var,
4429 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4430 if (0 == ret)
4431 {
4432 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004433 }
4434 }
4435
4436 if (HDD_WMM_USER_MODE_NO_QOS ==
4437 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4438 {
4439 /*QoS not enabled in cfg file*/
4440 pRoamProfile->uapsd_mask = 0;
4441 }
4442 else
4443 {
4444 /*QoS enabled, update uapsd mask from cfg file*/
4445 pRoamProfile->uapsd_mask =
4446 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4447 }
4448
4449 pRoamProfile->SSIDs.numOfSSIDs = 1;
4450 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4451 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
4452 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
4453 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4454 ssid, ssid_len);
4455
4456 if (bssid)
4457 {
4458 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4459 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4460 WNI_CFG_BSSID_LEN);
4461 /* Save BSSID in seperate variable as well, as RoamProfile
4462 BSSID is getting zeroed out in the association process. And in
4463 case of join failure we should send valid BSSID to supplicant
4464 */
4465 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4466 WNI_CFG_BSSID_LEN);
4467 }
4468
4469 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4470 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4471 {
4472 /*set gen ie*/
4473 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4474 /*set auth*/
4475 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4476 }
4477 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4478 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4479 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4480 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4481 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4482 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4483 )
4484 {
4485 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4486 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4487 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4488 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4489 eCSR_AUTH_TYPE_AUTOSWITCH;
4490 pWextState->roamProfile.AuthType.authType[0] =
4491 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4492 }
4493#ifdef FEATURE_WLAN_WAPI
4494 if (pAdapter->wapi_info.nWapiMode)
4495 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004496 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004497 switch (pAdapter->wapi_info.wapiAuthMode)
4498 {
4499 case WAPI_AUTH_MODE_PSK:
4500 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004501 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004502 pAdapter->wapi_info.wapiAuthMode);
4503 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4504 break;
4505 }
4506 case WAPI_AUTH_MODE_CERT:
4507 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004508 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004509 pAdapter->wapi_info.wapiAuthMode);
4510 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4511 break;
4512 }
4513 } // End of switch
4514 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4515 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4516 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004517 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004518 pRoamProfile->AuthType.numEntries = 1;
4519 pRoamProfile->EncryptionType.numEntries = 1;
4520 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4521 pRoamProfile->mcEncryptionType.numEntries = 1;
4522 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4523 }
4524 }
4525#endif /* FEATURE_WLAN_WAPI */
4526 pRoamProfile->csrPersona = pAdapter->device_mode;
4527
Jeff Johnson32d95a32012-09-10 13:15:23 -07004528 if( operatingChannel )
4529 {
4530 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4531 pRoamProfile->ChannelInfo.numOfChannels = 1;
4532 }
4533
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004534 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
4535 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
4536 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
4537 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004538 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
4539 */
4540 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4541 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
4542 eConnectionState_Connecting);
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004543
Jeff Johnson295189b2012-06-20 16:38:30 -07004544 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4545 pAdapter->sessionId, pRoamProfile, &roamId);
4546
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004547 if( (eHAL_STATUS_SUCCESS != status) &&
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304548 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
4549
4550 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004551 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
4552 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
4553 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304554 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004555 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304556 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004557
4558 pRoamProfile->ChannelInfo.ChannelList = NULL;
4559 pRoamProfile->ChannelInfo.numOfChannels = 0;
4560
Jeff Johnson295189b2012-06-20 16:38:30 -07004561 }
4562 else
4563 {
4564 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4565 return -EINVAL;
4566 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004567 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004568 return status;
4569}
4570
4571/*
4572 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4573 * This function is used to set the authentication type (OPEN/SHARED).
4574 *
4575 */
4576static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4577 enum nl80211_auth_type auth_type)
4578{
4579 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4580 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4581
4582 ENTER();
4583
4584 /*set authentication type*/
4585 switch (auth_type)
4586 {
4587 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4588 case NL80211_AUTHTYPE_AUTOMATIC:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07004589#ifdef WLAN_FEATURE_VOWIFI_11R
4590 case NL80211_AUTHTYPE_FT:
4591#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07004592 hddLog(VOS_TRACE_LEVEL_INFO,
4593 "%s: set authentication type to OPEN", __func__);
4594 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4595 break;
4596
4597 case NL80211_AUTHTYPE_SHARED_KEY:
4598 hddLog(VOS_TRACE_LEVEL_INFO,
4599 "%s: set authentication type to SHARED", __func__);
4600 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4601 break;
4602#ifdef FEATURE_WLAN_CCX
4603 case NL80211_AUTHTYPE_NETWORK_EAP:
4604 hddLog(VOS_TRACE_LEVEL_INFO,
4605 "%s: set authentication type to CCKM WPA", __func__);
4606 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4607 break;
4608#endif
4609
4610
4611 default:
4612 hddLog(VOS_TRACE_LEVEL_ERROR,
4613 "%s: Unsupported authentication type %d", __func__,
4614 auth_type);
4615 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4616 return -EINVAL;
4617 }
4618
4619 pWextState->roamProfile.AuthType.authType[0] =
4620 pHddStaCtx->conn_info.authType;
4621 return 0;
4622}
4623
4624/*
4625 * FUNCTION: wlan_hdd_set_akm_suite
4626 * This function is used to set the key mgmt type(PSK/8021x).
4627 *
4628 */
4629static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
4630 u32 key_mgmt
4631 )
4632{
4633 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4634 ENTER();
4635
4636 /*set key mgmt type*/
4637 switch(key_mgmt)
4638 {
4639 case WLAN_AKM_SUITE_PSK:
4640 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
4641 __func__);
4642 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
4643 break;
4644
4645 case WLAN_AKM_SUITE_8021X:
4646 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
4647 __func__);
4648 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
4649 break;
4650#ifdef FEATURE_WLAN_CCX
4651#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
4652#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
4653 case WLAN_AKM_SUITE_CCKM:
4654 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
4655 __func__);
4656 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
4657 break;
4658#endif
4659
4660 default:
4661 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
4662 __func__, key_mgmt);
4663 return -EINVAL;
4664
4665 }
4666 return 0;
4667}
4668
4669/*
4670 * FUNCTION: wlan_hdd_cfg80211_set_cipher
4671 * This function is used to set the encryption type
4672 * (NONE/WEP40/WEP104/TKIP/CCMP).
4673 */
4674static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
4675 u32 cipher,
4676 bool ucast
4677 )
4678{
4679 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4680 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4681 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4682
4683 ENTER();
4684
4685 if (!cipher)
4686 {
4687 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
4688 __func__, cipher);
4689 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4690 }
4691 else
4692 {
4693
4694 /*set encryption method*/
4695 switch (cipher)
4696 {
4697 case IW_AUTH_CIPHER_NONE:
4698 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4699 break;
4700
4701 case WLAN_CIPHER_SUITE_WEP40:
4702 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4703 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4704 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
4705 else
4706 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4707 break;
4708
4709 case WLAN_CIPHER_SUITE_WEP104:
4710 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4711 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4712 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
4713 else
4714 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
4715 break;
4716
4717 case WLAN_CIPHER_SUITE_TKIP:
4718 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
4719 break;
4720
4721 case WLAN_CIPHER_SUITE_CCMP:
4722 encryptionType = eCSR_ENCRYPT_TYPE_AES;
4723 break;
4724#ifdef FEATURE_WLAN_WAPI
4725 case WLAN_CIPHER_SUITE_SMS4:
4726 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
4727 break;
4728#endif
4729
4730#ifdef FEATURE_WLAN_CCX
4731 case WLAN_CIPHER_SUITE_KRK:
4732 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
4733 break;
4734#endif
4735 default:
4736 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
4737 __func__, cipher);
4738 return -EOPNOTSUPP;
4739 }
4740 }
4741
4742 if (ucast)
4743 {
4744 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
4745 __func__, encryptionType);
4746 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
4747 pWextState->roamProfile.EncryptionType.numEntries = 1;
4748 pWextState->roamProfile.EncryptionType.encryptionType[0] =
4749 encryptionType;
4750 }
4751 else
4752 {
4753 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
4754 __func__, encryptionType);
4755 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
4756 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
4757 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
4758 }
4759
4760 return 0;
4761}
4762
4763
4764/*
4765 * FUNCTION: wlan_hdd_cfg80211_set_ie
4766 * This function is used to parse WPA/RSN IE's.
4767 */
4768int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
4769 u8 *ie,
4770 size_t ie_len
4771 )
4772{
4773 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4774 u8 *genie = ie;
4775 v_U16_t remLen = ie_len;
4776#ifdef FEATURE_WLAN_WAPI
4777 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
4778 u16 *tmp;
4779 v_U16_t akmsuiteCount;
4780 int *akmlist;
4781#endif
4782 ENTER();
4783
4784 /* clear previous assocAddIE */
4785 pWextState->assocAddIE.length = 0;
4786 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
4787
4788 while (remLen >= 2)
4789 {
4790 v_U16_t eLen = 0;
4791 v_U8_t elementId;
4792 elementId = *genie++;
4793 eLen = *genie++;
4794 remLen -= 2;
4795
4796 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
4797 __func__, elementId, eLen);
4798
4799 switch ( elementId )
4800 {
4801 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004802 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 -07004803 {
4804 hddLog(VOS_TRACE_LEVEL_ERROR,
4805 "%s: Invalid WPA IE", __func__);
4806 return -EINVAL;
4807 }
4808 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
4809 {
4810 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4811 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
4812 __func__, eLen + 2);
4813
4814 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4815 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004816 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
4817 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004818 VOS_ASSERT(0);
4819 return -ENOMEM;
4820 }
4821 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4822 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4823 pWextState->assocAddIE.length += eLen + 2;
4824
4825 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
4826 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4827 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4828 }
4829 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
4830 {
4831 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
4832 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4833 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
4834 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
4835 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
4836 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004837 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
4838 P2P_OUI_TYPE_SIZE))
4839 /*Consider P2P IE, only for P2P Client */
4840 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4841 {
4842 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4843 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
4844 __func__, eLen + 2);
4845
4846 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4847 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004848 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4849 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004850 VOS_ASSERT(0);
4851 return -ENOMEM;
4852 }
4853 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4854 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4855 pWextState->assocAddIE.length += eLen + 2;
4856
4857 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4858 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4859 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004860#ifdef WLAN_FEATURE_WFD
4861 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
4862 WFD_OUI_TYPE_SIZE))
4863 /*Consider WFD IE, only for P2P Client */
4864 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4865 {
4866 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4867 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
4868 __func__, eLen + 2);
4869
4870 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4871 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004872 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4873 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004874 VOS_ASSERT(0);
4875 return -ENOMEM;
4876 }
4877 // WFD IE is saved to Additional IE ; it should be accumulated to handle
4878 // WPS IE + P2P IE + WFD IE
4879 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4880 pWextState->assocAddIE.length += eLen + 2;
4881
4882 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4883 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4884 }
4885#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004886 /* Appending HS 2.0 Indication Element in Assiciation Request */
4887 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004888 HS20_OUI_TYPE_SIZE)) )
4889 {
4890 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4891 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
4892 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004893
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004894 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4895 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004896 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4897 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004898 VOS_ASSERT(0);
4899 return -ENOMEM;
4900 }
4901 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4902 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004903
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004904 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4905 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4906 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004907
Jeff Johnson295189b2012-06-20 16:38:30 -07004908 break;
4909 case DOT11F_EID_RSN:
4910 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
4911 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4912 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
4913 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
4914 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
4915 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004916 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
4917 case DOT11F_EID_EXTCAP:
4918 {
4919 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4920 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
4921 __func__, eLen + 2);
4922
4923 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4924 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004925 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4926 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004927 VOS_ASSERT(0);
4928 return -ENOMEM;
4929 }
4930 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4931 pWextState->assocAddIE.length += eLen + 2;
4932
4933 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4934 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4935 break;
4936 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004937#ifdef FEATURE_WLAN_WAPI
4938 case WLAN_EID_WAPI:
4939 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
4940 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
4941 pAdapter->wapi_info.nWapiMode);
4942 tmp = (u16 *)ie;
4943 tmp = tmp + 2; // Skip element Id and Len, Version
4944 akmsuiteCount = WPA_GET_LE16(tmp);
4945 tmp = tmp + 1;
4946 akmlist = (int *)(tmp);
4947 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
4948 {
4949 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
4950 }
4951 else
4952 {
4953 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
4954 VOS_ASSERT(0);
4955 return -EINVAL;
4956 }
4957
4958 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
4959 {
4960 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004961 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004962 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
4963 }
4964 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
4965 {
4966 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004967 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004968 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
4969 }
4970 break;
4971#endif
4972 default:
4973 hddLog (VOS_TRACE_LEVEL_ERROR,
4974 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004975 /* when Unknown IE is received we should break and continue
4976 * to the next IE in the buffer instead we were returning
4977 * so changing this to break */
4978 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07004979 }
4980 genie += eLen;
4981 remLen -= eLen;
4982 }
4983 EXIT();
4984 return 0;
4985}
4986
4987/*
4988 * FUNCTION: wlan_hdd_cfg80211_set_privacy
4989 * This function is used to initialize the security
4990 * parameters during connect operation.
4991 */
4992int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
4993 struct cfg80211_connect_params *req
4994 )
4995{
4996 int status = 0;
4997 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4998 ENTER();
4999
5000 /*set wpa version*/
5001 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5002
5003 if (req->crypto.wpa_versions)
5004 {
5005 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
5006 && ( (req->ie_len)
5007 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
5008 // Make sure that it is including a WPA IE.
5009 /* Currently NL is putting WPA version 1 even for open,
5010 * since p2p ie is also put in same buffer.
5011 * */
5012 {
5013 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5014 }
5015 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
5016 {
5017 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5018 }
5019 }
5020
5021 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
5022 pWextState->wpaVersion);
5023
5024 /*set authentication type*/
5025 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
5026
5027 if (0 > status)
5028 {
5029 hddLog(VOS_TRACE_LEVEL_ERROR,
5030 "%s: failed to set authentication type ", __func__);
5031 return status;
5032 }
5033
5034 /*set key mgmt type*/
5035 if (req->crypto.n_akm_suites)
5036 {
5037 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
5038 if (0 > status)
5039 {
5040 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
5041 __func__);
5042 return status;
5043 }
5044 }
5045
5046 /*set pairwise cipher type*/
5047 if (req->crypto.n_ciphers_pairwise)
5048 {
5049 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
5050 req->crypto.ciphers_pairwise[0], true);
5051 if (0 > status)
5052 {
5053 hddLog(VOS_TRACE_LEVEL_ERROR,
5054 "%s: failed to set unicast cipher type", __func__);
5055 return status;
5056 }
5057 }
5058 else
5059 {
5060 /*Reset previous cipher suite to none*/
5061 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
5062 if (0 > status)
5063 {
5064 hddLog(VOS_TRACE_LEVEL_ERROR,
5065 "%s: failed to set unicast cipher type", __func__);
5066 return status;
5067 }
5068 }
5069
5070 /*set group cipher type*/
5071 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
5072 false);
5073
5074 if (0 > status)
5075 {
5076 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
5077 __func__);
5078 return status;
5079 }
5080
5081 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
5082 if (req->ie_len)
5083 {
5084 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
5085 if ( 0 > status)
5086 {
5087 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
5088 __func__);
5089 return status;
5090 }
5091 }
5092
5093 /*incase of WEP set default key information*/
5094 if (req->key && req->key_len)
5095 {
5096 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
5097 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
5098 )
5099 {
5100 if ( IW_AUTH_KEY_MGMT_802_1X
5101 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
5102 {
5103 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
5104 __func__);
5105 return -EOPNOTSUPP;
5106 }
5107 else
5108 {
5109 u8 key_len = req->key_len;
5110 u8 key_idx = req->key_idx;
5111
5112 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
5113 && (CSR_MAX_NUM_KEY > key_idx)
5114 )
5115 {
5116 hddLog(VOS_TRACE_LEVEL_INFO,
5117 "%s: setting default wep key, key_idx = %hu key_len %hu",
5118 __func__, key_idx, key_len);
5119 vos_mem_copy(
5120 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
5121 req->key, key_len);
5122 pWextState->roamProfile.Keys.KeyLength[key_idx] =
5123 (u8)key_len;
5124 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
5125 }
5126 }
5127 }
5128 }
5129
5130 return status;
5131}
5132
5133/*
5134 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5135 * This function is used to initialize the security
5136 * parameters during connect operation.
5137 */
5138static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
5139 struct net_device *ndev,
5140 struct cfg80211_connect_params *req
5141 )
5142{
5143 int status = 0;
5144 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
5145 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
5146 hdd_context_t *pHddCtx = NULL;
5147
5148 ENTER();
5149
5150 hddLog(VOS_TRACE_LEVEL_INFO,
5151 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5152
5153 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5154 {
5155 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5156 "%s:LOGP in Progress. Ignore!!!", __func__);
5157 return -EAGAIN;
5158 }
5159
5160#ifdef WLAN_BTAMP_FEATURE
5161 //Infra connect not supported when AMP traffic is on.
5162 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
5163 {
5164 hddLog(VOS_TRACE_LEVEL_ERROR,
5165 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005166 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07005167 }
5168#endif
5169 /*initialise security parameters*/
5170 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
5171
5172 if ( 0 > status)
5173 {
5174 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
5175 __func__);
5176 return status;
5177 }
5178
5179 //If Device Mode is Station Concurrent Sessions Exit BMps
Jeff Johnsona8a1a482012-12-12 16:49:33 -08005180 //P2P Mode will be taken care in Open/close adapter
Jeff Johnson295189b2012-06-20 16:38:30 -07005181 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
5182 (vos_concurrent_sessions_running()))
5183 {
5184 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5185
5186 if (NULL != pVosContext)
5187 {
5188 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5189 if(NULL != pHddCtx)
5190 {
5191 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
5192 }
5193 }
5194 }
5195
Mohit Khanna765234a2012-09-11 15:08:35 -07005196 if ( req->channel )
5197 {
5198 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5199 req->ssid_len, req->bssid,
5200 req->channel->hw_value);
5201 }
5202 else
5203 {
5204 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5205 req->ssid_len, req->bssid,
5206 0);
5207 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005208
5209 if (0 > status)
5210 {
5211 //ReEnable BMPS if disabled
5212 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5213 (NULL != pHddCtx))
5214 {
5215 //ReEnable Bmps and Imps back
5216 hdd_enable_bmps_imps(pHddCtx);
5217 }
5218
5219 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5220 return status;
5221 }
5222 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
5223 EXIT();
5224 return status;
5225}
5226
5227
5228/*
5229 * FUNCTION: wlan_hdd_cfg80211_disconnect
5230 * This function is used to issue a disconnect request to SME
5231 */
5232static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
5233 struct net_device *dev,
5234 u16 reason
5235 )
5236{
5237 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5238 tCsrRoamProfile *pRoamProfile =
5239 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
5240 int status = 0;
5241 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005242#ifdef FEATURE_WLAN_TDLS
5243 tANI_U8 staIdx;
5244#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005245
5246 ENTER();
5247
5248 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
5249 __func__,pAdapter->device_mode);
5250
5251 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5252 __func__, reason);
5253
5254 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
5255 {
5256 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5257 "%s:LOGP in Progress. Ignore!!!",__func__);
5258 return -EAGAIN;
5259 }
5260 if (NULL != pRoamProfile)
5261 {
5262 /*issue disconnect request to SME, if station is in connected state*/
5263 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
5264 {
5265 eCsrRoamDisconnectReason reasonCode =
5266 eCSR_DISCONNECT_REASON_UNSPECIFIED;
5267 switch(reason)
5268 {
5269 case WLAN_REASON_MIC_FAILURE:
5270 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
5271 break;
5272
5273 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
5274 case WLAN_REASON_DISASSOC_AP_BUSY:
5275 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
5276 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
5277 break;
5278
5279 case WLAN_REASON_PREV_AUTH_NOT_VALID:
5280 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
5281 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
5282 break;
5283
5284 case WLAN_REASON_DEAUTH_LEAVING:
5285 default:
5286 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
5287 break;
5288 }
5289 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5290 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
5291 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5292
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005293#ifdef FEATURE_WLAN_TDLS
5294 /* First clean up the tdls peers if any */
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005295 for (staIdx = 1 ; staIdx <= HDD_MAX_NUM_TDLS_STA; staIdx++)
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005296 {
5297 if (pHddStaCtx->conn_info.staId[staIdx])
5298 {
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005299 uint8 *mac;
5300 mac = pHddStaCtx->conn_info.peerMacAddress[staIdx].bytes;
5301 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
5302 "%s: call sme_DeleteTdlsPeerSta staId %d sessionId %d %02x:%02x:%02x:%02x:%02x:%02x",
5303 __func__, pHddStaCtx->conn_info.staId[staIdx], pAdapter->sessionId,
5304 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] );
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005305 sme_DeleteTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
5306 pAdapter->sessionId,
5307 pHddStaCtx->conn_info.peerMacAddress[staIdx].bytes);
5308 }
5309 }
5310#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005311 /*issue disconnect*/
5312 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5313 pAdapter->sessionId, reasonCode);
5314
5315 if ( 0 != status)
5316 {
5317 hddLog(VOS_TRACE_LEVEL_ERROR,
5318 "%s csrRoamDisconnect failure, returned %d \n",
5319 __func__, (int)status );
5320 return -EINVAL;
5321 }
5322
5323 wait_for_completion_interruptible_timeout(
5324 &pAdapter->disconnect_comp_var,
5325 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5326
5327
5328 /*stop tx queues*/
5329 netif_tx_disable(dev);
5330 netif_carrier_off(dev);
5331 }
5332 }
5333 else
5334 {
5335 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
5336 }
5337
5338 return status;
5339}
5340
5341/*
5342 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
5343 * This function is used to initialize the security
5344 * settings in IBSS mode.
5345 */
5346static int wlan_hdd_cfg80211_set_privacy_ibss(
5347 hdd_adapter_t *pAdapter,
5348 struct cfg80211_ibss_params *params
5349 )
5350{
5351 int status = 0;
5352 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5353 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5354 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5355
5356 ENTER();
5357
5358 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5359
5360 if (params->ie_len && ( NULL != params->ie) )
5361 {
5362 if (WLAN_EID_RSN == params->ie[0])
5363 {
5364 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5365 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5366 }
5367 else
5368 {
5369 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5370 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5371 }
5372 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
5373
5374 if (0 > status)
5375 {
5376 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
5377 __func__);
5378 return status;
5379 }
5380 }
5381
5382 pWextState->roamProfile.AuthType.authType[0] =
5383 pHddStaCtx->conn_info.authType =
5384 eCSR_AUTH_TYPE_OPEN_SYSTEM;
5385
5386 if (params->privacy)
5387 {
5388 /* Security enabled IBSS, At this time there is no information available
5389 * about the security paramters, so initialise the encryption type to
5390 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
5391 * The correct security parameters will be updated later in
5392 * wlan_hdd_cfg80211_add_key */
5393 /* Hal expects encryption type to be set inorder
5394 *enable privacy bit in beacons */
5395
5396 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5397 }
5398
5399 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5400 pWextState->roamProfile.EncryptionType.numEntries = 1;
5401 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
5402
5403 return status;
5404}
5405
5406/*
5407 * FUNCTION: wlan_hdd_cfg80211_join_ibss
5408 * This function is used to create/join an IBSS
5409 */
5410static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
5411 struct net_device *dev,
5412 struct cfg80211_ibss_params *params
5413 )
5414{
5415 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5416 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5417 tCsrRoamProfile *pRoamProfile;
5418 int status;
5419 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5420
5421 ENTER();
5422
5423 hddLog(VOS_TRACE_LEVEL_INFO,
5424 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5425
5426 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5427 {
5428 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5429 "%s:LOGP in Progress. Ignore!!!", __func__);
5430 return -EAGAIN;
5431 }
5432
5433 if (NULL == pWextState)
5434 {
5435 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5436 __func__);
5437 return -EIO;
5438 }
5439
5440 pRoamProfile = &pWextState->roamProfile;
5441
5442 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
5443 {
5444 hddLog (VOS_TRACE_LEVEL_ERROR,
5445 "%s Interface type is not set to IBSS \n", __func__);
5446 return -EINVAL;
5447 }
5448
5449 /* Set Channel */
5450 if (NULL != params->channel)
5451 {
5452 u8 channelNum;
5453 if (IEEE80211_BAND_5GHZ == params->channel->band)
5454 {
5455 hddLog(VOS_TRACE_LEVEL_ERROR,
5456 "%s: IBSS join is called with unsupported band %d",
5457 __func__, params->channel->band);
5458 return -EOPNOTSUPP;
5459 }
5460
5461 /* Get channel number */
5462 channelNum =
5463 ieee80211_frequency_to_channel(params->channel->center_freq);
5464
5465 /*TODO: use macro*/
5466 if (14 >= channelNum)
5467 {
5468 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5469 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5470 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5471 int indx;
5472
5473 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5474 validChan, &numChans))
5475 {
5476 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
5477 __func__);
5478 return -EOPNOTSUPP;
5479 }
5480
5481 for (indx = 0; indx < numChans; indx++)
5482 {
5483 if (channelNum == validChan[indx])
5484 {
5485 break;
5486 }
5487 }
5488 if (indx >= numChans)
5489 {
5490 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
5491 __func__, channelNum);
5492 return -EINVAL;
5493 }
5494 /* Set the Operational Channel */
5495 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
5496 channelNum);
5497 pRoamProfile->ChannelInfo.numOfChannels = 1;
5498 pHddStaCtx->conn_info.operationChannel = channelNum;
5499 pRoamProfile->ChannelInfo.ChannelList =
5500 &pHddStaCtx->conn_info.operationChannel;
5501 }
5502 else
5503 {
5504 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5505 __func__, channelNum);
5506 return -EINVAL;
5507 }
5508 }
5509
5510 /* Initialize security parameters */
5511 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5512 if (status < 0)
5513 {
5514 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5515 __func__);
5516 return status;
5517 }
5518
5519 /* Issue connect start */
5520 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005521 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005522
5523 if (0 > status)
5524 {
5525 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5526 return status;
5527 }
5528
5529 return 0;
5530}
5531
5532/*
5533 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5534 * This function is used to leave an IBSS
5535 */
5536static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5537 struct net_device *dev
5538 )
5539{
5540 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5541 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5542 tCsrRoamProfile *pRoamProfile;
5543
5544 ENTER();
5545
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005546 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5547 {
5548 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5549 "%s:LOGP in Progress. Ignore!!!", __func__);
5550 return -EAGAIN;
5551 }
5552
Jeff Johnson295189b2012-06-20 16:38:30 -07005553 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5554 if (NULL == pWextState)
5555 {
5556 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5557 __func__);
5558 return -EIO;
5559 }
5560
5561 pRoamProfile = &pWextState->roamProfile;
5562
5563 /* Issue disconnect only if interface type is set to IBSS */
5564 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5565 {
5566 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5567 __func__);
5568 return -EINVAL;
5569 }
5570
5571 /* Issue Disconnect request */
5572 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5573 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5574 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5575
5576 return 0;
5577}
5578
5579/*
5580 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5581 * This function is used to set the phy parameters
5582 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5583 */
5584static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5585 u32 changed)
5586{
5587 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5588 tHalHandle hHal = pHddCtx->hHal;
5589
5590 ENTER();
5591
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005592 if ( pHddCtx->isLogpInProgress )
5593 {
5594 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5595 "%s:LOGP in Progress. Ignore!!!", __func__);
5596 return -EAGAIN;
5597 }
5598
Jeff Johnson295189b2012-06-20 16:38:30 -07005599 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
5600 {
5601 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
5602 WNI_CFG_RTS_THRESHOLD_STAMAX :
5603 wiphy->rts_threshold;
5604
5605 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
5606 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
5607 {
5608 hddLog(VOS_TRACE_LEVEL_ERROR,
5609 "%s: Invalid RTS Threshold value %hu",
5610 __func__, rts_threshold);
5611 return -EINVAL;
5612 }
5613
5614 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
5615 rts_threshold, ccmCfgSetCallback,
5616 eANI_BOOLEAN_TRUE))
5617 {
5618 hddLog(VOS_TRACE_LEVEL_ERROR,
5619 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
5620 __func__, rts_threshold);
5621 return -EIO;
5622 }
5623
5624 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
5625 rts_threshold);
5626 }
5627
5628 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
5629 {
5630 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
5631 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
5632 wiphy->frag_threshold;
5633
5634 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
5635 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
5636 {
5637 hddLog(VOS_TRACE_LEVEL_ERROR,
5638 "%s: Invalid frag_threshold value %hu", __func__,
5639 frag_threshold);
5640 return -EINVAL;
5641 }
5642
5643 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
5644 frag_threshold, ccmCfgSetCallback,
5645 eANI_BOOLEAN_TRUE))
5646 {
5647 hddLog(VOS_TRACE_LEVEL_ERROR,
5648 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
5649 __func__, frag_threshold);
5650 return -EIO;
5651 }
5652
5653 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
5654 frag_threshold);
5655 }
5656
5657 if ((changed & WIPHY_PARAM_RETRY_SHORT)
5658 || (changed & WIPHY_PARAM_RETRY_LONG))
5659 {
5660 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
5661 wiphy->retry_short :
5662 wiphy->retry_long;
5663
5664 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
5665 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
5666 {
5667 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
5668 __func__, retry_value);
5669 return -EINVAL;
5670 }
5671
5672 if (changed & WIPHY_PARAM_RETRY_SHORT)
5673 {
5674 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
5675 retry_value, ccmCfgSetCallback,
5676 eANI_BOOLEAN_TRUE))
5677 {
5678 hddLog(VOS_TRACE_LEVEL_ERROR,
5679 "%s: ccmCfgSetInt failed for long retry count %hu",
5680 __func__, retry_value);
5681 return -EIO;
5682 }
5683 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
5684 __func__, retry_value);
5685 }
5686 else if (changed & WIPHY_PARAM_RETRY_SHORT)
5687 {
5688 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
5689 retry_value, ccmCfgSetCallback,
5690 eANI_BOOLEAN_TRUE))
5691 {
5692 hddLog(VOS_TRACE_LEVEL_ERROR,
5693 "%s: ccmCfgSetInt failed for short retry count %hu",
5694 __func__, retry_value);
5695 return -EIO;
5696 }
5697 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
5698 __func__, retry_value);
5699 }
5700 }
5701
5702 return 0;
5703}
5704
5705/*
5706 * FUNCTION: wlan_hdd_cfg80211_set_txpower
5707 * This function is used to set the txpower
5708 */
5709static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
5710#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
5711 enum tx_power_setting type,
5712#else
5713 enum nl80211_tx_power_setting type,
5714#endif
5715 int dbm)
5716{
5717 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5718 tHalHandle hHal = pHddCtx->hHal;
5719 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5720 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5721
5722 ENTER();
5723
5724 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
5725 dbm, ccmCfgSetCallback,
5726 eANI_BOOLEAN_TRUE))
5727 {
5728 hddLog(VOS_TRACE_LEVEL_ERROR,
5729 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
5730 return -EIO;
5731 }
5732
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005733 if ( pHddCtx->isLogpInProgress )
5734 {
5735 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5736 "%s:LOGP in Progress. Ignore!!!", __func__);
5737 return -EAGAIN;
5738 }
5739
Jeff Johnson295189b2012-06-20 16:38:30 -07005740 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
5741 dbm);
5742
5743 switch(type)
5744 {
5745 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
5746 /* Fall through */
5747 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
5748 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
5749 {
5750 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
5751 __func__);
5752 return -EIO;
5753 }
5754 break;
5755 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
5756 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
5757 __func__);
5758 return -EOPNOTSUPP;
5759 break;
5760 default:
5761 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
5762 __func__, type);
5763 return -EIO;
5764 }
5765
5766 return 0;
5767}
5768
5769/*
5770 * FUNCTION: wlan_hdd_cfg80211_get_txpower
5771 * This function is used to read the txpower
5772 */
5773static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
5774{
5775
5776 hdd_adapter_t *pAdapter;
5777 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5778
Jeff Johnsone7245742012-09-05 17:12:55 -07005779 ENTER();
5780
Jeff Johnson295189b2012-06-20 16:38:30 -07005781 if (NULL == pHddCtx)
5782 {
5783 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
5784 *dbm = 0;
5785 return -ENOENT;
5786 }
5787
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005788 if ( pHddCtx->isLogpInProgress )
5789 {
5790 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5791 "%s:LOGP in Progress. Ignore!!!", __func__);
5792 return -EAGAIN;
5793 }
5794
Jeff Johnson295189b2012-06-20 16:38:30 -07005795 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5796 if (NULL == pAdapter)
5797 {
5798 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
5799 return -ENOENT;
5800 }
5801
5802 wlan_hdd_get_classAstats(pAdapter);
5803 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
5804
Jeff Johnsone7245742012-09-05 17:12:55 -07005805 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005806 return 0;
5807}
5808
5809static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
5810 u8* mac, struct station_info *sinfo)
5811{
5812 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5813 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5814 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
5815 tANI_U8 rate_flags;
5816
5817 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5818 hdd_config_t *pCfg = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07005819
5820 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
5821 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
5822 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
5823 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
5824 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
5825 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
5826 tANI_U16 maxRate = 0;
5827 tANI_U16 myRate;
5828 tANI_U16 currentRate = 0;
5829 tANI_U8 maxSpeedMCS = 0;
5830 tANI_U8 maxMCSIdx = 0;
5831 tANI_U8 rateFlag = 1;
5832 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005833 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07005834
Jeff Johnsone7245742012-09-05 17:12:55 -07005835 ENTER();
5836
Jeff Johnson295189b2012-06-20 16:38:30 -07005837 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
5838 (0 == ssidlen))
5839 {
5840 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
5841 " Invalid ssidlen, %d", __func__, ssidlen);
5842 /*To keep GUI happy*/
5843 return 0;
5844 }
5845
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005846 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5847 {
5848 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5849 "%s:LOGP in Progress. Ignore!!!", __func__);
5850 return -EAGAIN;
5851 }
5852
Jeff Johnson295189b2012-06-20 16:38:30 -07005853 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
5854 sinfo->filled |= STATION_INFO_SIGNAL;
5855
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005856 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005857 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
5858
5859 //convert to the UI units of 100kbps
5860 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
5861
5862#ifdef LINKSPEED_DEBUG_ENABLED
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005863 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 -07005864 sinfo->signal,
5865 pCfg->reportMaxLinkSpeed,
5866 myRate,
5867 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005868 (int) pCfg->linkSpeedRssiMid,
5869 (int) pCfg->linkSpeedRssiLow,
5870 (int) rate_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005871#endif //LINKSPEED_DEBUG_ENABLED
5872
5873 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
5874 {
5875 // we do not want to necessarily report the current speed
5876 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
5877 {
5878 // report the max possible speed
5879 rssidx = 0;
5880 }
5881 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
5882 {
5883 // report the max possible speed with RSSI scaling
5884 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
5885 {
5886 // report the max possible speed
5887 rssidx = 0;
5888 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005889 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07005890 {
5891 // report middle speed
5892 rssidx = 1;
5893 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005894 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
5895 {
5896 // report middle speed
5897 rssidx = 2;
5898 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005899 else
5900 {
5901 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005902 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07005903 }
5904 }
5905 else
5906 {
5907 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
5908 hddLog(VOS_TRACE_LEVEL_ERROR,
5909 "%s: Invalid value for reportMaxLinkSpeed: %u",
5910 __func__, pCfg->reportMaxLinkSpeed);
5911 rssidx = 0;
5912 }
5913
5914 maxRate = 0;
5915
5916 /* Get Basic Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05305917 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_OPERATIONAL_RATE_SET,
5918 OperationalRates, &ORLeng))
5919 {
5920 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
5921 /*To keep GUI happy*/
5922 return 0;
5923 }
5924
Jeff Johnson295189b2012-06-20 16:38:30 -07005925 for (i = 0; i < ORLeng; i++)
5926 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005927 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005928 {
5929 /* Validate Rate Set */
5930 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
5931 {
5932 currentRate = supported_data_rate[j].supported_rate[rssidx];
5933 break;
5934 }
5935 }
5936 /* Update MAX rate */
5937 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5938 }
5939
5940 /* Get Extended Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05305941 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
5942 ExtendedRates, &ERLeng))
5943 {
5944 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
5945 /*To keep GUI happy*/
5946 return 0;
5947 }
5948
Jeff Johnson295189b2012-06-20 16:38:30 -07005949 for (i = 0; i < ERLeng; i++)
5950 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005951 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005952 {
5953 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
5954 {
5955 currentRate = supported_data_rate[j].supported_rate[rssidx];
5956 break;
5957 }
5958 }
5959 /* Update MAX rate */
5960 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5961 }
5962
5963 /* Get MCS Rate Set -- but only if we are connected at MCS
5964 rates or if we are always reporting max speed or if we have
5965 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005966 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07005967 {
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05305968 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_CURRENT_MCS_SET,
5969 MCSRates, &MCSLeng))
5970 {
5971 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
5972 /*To keep GUI happy*/
5973 return 0;
5974 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005975 rateFlag = 0;
5976 if (rate_flags & eHAL_TX_RATE_HT40)
5977 {
5978 rateFlag |= 1;
5979 }
5980 if (rate_flags & eHAL_TX_RATE_SGI)
5981 {
5982 rateFlag |= 2;
5983 }
5984
5985 for (i = 0; i < MCSLeng; i++)
5986 {
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005987 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
5988 for (j = 0; j < temp; j++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005989 {
5990 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
5991 {
5992 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
5993 break;
5994 }
5995 }
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005996 if ((j < temp) && (currentRate > maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07005997 {
5998 maxRate = currentRate;
5999 maxSpeedMCS = 1;
6000 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
6001 }
6002 }
6003 }
6004
6005 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006006 if (((maxRate < myRate) && (0 == rssidx)) ||
6007 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006008 {
6009 maxRate = myRate;
6010 if (rate_flags & eHAL_TX_RATE_LEGACY)
6011 {
6012 maxSpeedMCS = 0;
6013 }
6014 else
6015 {
6016 maxSpeedMCS = 1;
6017 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6018 }
6019 }
6020
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006021 if ((!maxSpeedMCS) || (0 != rssidx))
Jeff Johnson295189b2012-06-20 16:38:30 -07006022 {
6023 sinfo->txrate.legacy = maxRate;
6024#ifdef LINKSPEED_DEBUG_ENABLED
6025 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
6026#endif //LINKSPEED_DEBUG_ENABLED
6027 }
6028 else
6029 {
6030 sinfo->txrate.mcs = maxMCSIdx;
6031 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6032 if (rate_flags & eHAL_TX_RATE_SGI)
6033 {
6034 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6035 }
6036 if (rate_flags & eHAL_TX_RATE_HT40)
6037 {
6038 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6039 }
6040#ifdef LINKSPEED_DEBUG_ENABLED
6041 pr_info("Reporting MCS rate %d flags %x\n",
6042 sinfo->txrate.mcs,
6043 sinfo->txrate.flags );
6044#endif //LINKSPEED_DEBUG_ENABLED
6045 }
6046 }
6047 else
6048 {
6049 // report current rate instead of max rate
6050
6051 if (rate_flags & eHAL_TX_RATE_LEGACY)
6052 {
6053 //provide to the UI in units of 100kbps
6054 sinfo->txrate.legacy = myRate;
6055#ifdef LINKSPEED_DEBUG_ENABLED
6056 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
6057#endif //LINKSPEED_DEBUG_ENABLED
6058 }
6059 else
6060 {
6061 //must be MCS
6062 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6063 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6064 if (rate_flags & eHAL_TX_RATE_SGI)
6065 {
6066 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6067 }
6068 if (rate_flags & eHAL_TX_RATE_HT40)
6069 {
6070 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6071 }
6072#ifdef LINKSPEED_DEBUG_ENABLED
6073 pr_info("Reporting actual MCS rate %d flags %x\n",
6074 sinfo->txrate.mcs,
6075 sinfo->txrate.flags );
6076#endif //LINKSPEED_DEBUG_ENABLED
6077 }
6078 }
6079 sinfo->filled |= STATION_INFO_TX_BITRATE;
6080
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006081 sinfo->tx_packets =
6082 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
6083 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
6084 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
6085 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
6086
6087 sinfo->tx_retries =
6088 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
6089 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
6090 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
6091 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
6092
6093 sinfo->tx_failed =
6094 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
6095 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
6096 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
6097 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
6098
6099 sinfo->filled |=
6100 STATION_INFO_TX_PACKETS |
6101 STATION_INFO_TX_RETRIES |
6102 STATION_INFO_TX_FAILED;
6103
6104 EXIT();
6105 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006106}
6107
6108static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
6109 struct net_device *dev, bool mode, v_SINT_t timeout)
6110{
6111 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6112 VOS_STATUS vos_status;
6113
Jeff Johnsone7245742012-09-05 17:12:55 -07006114 ENTER();
6115
Jeff Johnson295189b2012-06-20 16:38:30 -07006116 if (NULL == pAdapter)
6117 {
6118 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6119 return -ENODEV;
6120 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006121 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6122 {
6123 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6124 "%s:LOGP in Progress. Ignore!!!", __func__);
6125 return -EAGAIN;
6126 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006127
6128 /**The get power cmd from the supplicant gets updated by the nl only
6129 *on successful execution of the function call
6130 *we are oppositely mapped w.r.t mode in the driver
6131 **/
6132 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
6133
Jeff Johnsone7245742012-09-05 17:12:55 -07006134 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006135 if (VOS_STATUS_E_FAILURE == vos_status)
6136 {
6137 return -EINVAL;
6138 }
6139 return 0;
6140}
6141
6142
6143#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6144static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
6145 struct net_device *netdev,
6146 u8 key_index)
6147{
Jeff Johnsone7245742012-09-05 17:12:55 -07006148 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006149 return 0;
6150}
6151#endif //LINUX_VERSION_CODE
6152
6153#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
6154static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6155 struct net_device *dev,
6156 struct ieee80211_txq_params *params)
6157{
Jeff Johnsone7245742012-09-05 17:12:55 -07006158 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006159 return 0;
6160}
6161#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6162static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6163 struct ieee80211_txq_params *params)
6164{
Jeff Johnsone7245742012-09-05 17:12:55 -07006165 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006166 return 0;
6167}
6168#endif //LINUX_VERSION_CODE
6169
6170static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
6171 struct net_device *dev, u8 *mac)
6172{
6173 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006174 VOS_STATUS vos_status;
6175 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006176
Jeff Johnsone7245742012-09-05 17:12:55 -07006177 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006178 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6179 {
6180 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6181 return -EINVAL;
6182 }
6183
6184 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6185 {
6186 hddLog( LOGE,
6187 "%s: Wlan Load/Unload is in progress", __func__);
6188 return -EBUSY;
6189 }
6190
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006191 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6192 {
6193 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6194 "%s:LOGP in Progress. Ignore!!!", __func__);
6195 return -EAGAIN;
6196 }
6197
Jeff Johnson295189b2012-06-20 16:38:30 -07006198 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006199 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006200 )
6201 {
6202 if( NULL == mac )
6203 {
6204 v_U16_t i;
6205 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
6206 {
6207 if(pAdapter->aStaInfo[i].isUsed)
6208 {
6209 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
6210 hddLog(VOS_TRACE_LEVEL_INFO,
6211 "%s: Delete STA with MAC::"
6212 "%02x:%02x:%02x:%02x:%02x:%02x",
6213 __func__,
6214 macAddr[0], macAddr[1], macAddr[2],
6215 macAddr[3], macAddr[4], macAddr[5]);
6216 hdd_softap_sta_deauth(pAdapter, macAddr);
6217 }
6218 }
6219 }
6220 else
6221 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006222
6223 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
6224 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6225 {
6226 hddLog(VOS_TRACE_LEVEL_INFO,
6227 "%s: Skip this DEL STA as this is not used::"
6228 "%02x:%02x:%02x:%02x:%02x:%02x",
6229 __func__,
6230 mac[0], mac[1], mac[2],
6231 mac[3], mac[4], mac[5]);
6232 return -ENOENT;
6233 }
6234
6235 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
6236 {
6237 hddLog(VOS_TRACE_LEVEL_INFO,
6238 "%s: Skip this DEL STA as deauth is in progress::"
6239 "%02x:%02x:%02x:%02x:%02x:%02x",
6240 __func__,
6241 mac[0], mac[1], mac[2],
6242 mac[3], mac[4], mac[5]);
6243 return -ENOENT;
6244 }
6245
6246 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
6247
Jeff Johnson295189b2012-06-20 16:38:30 -07006248 hddLog(VOS_TRACE_LEVEL_INFO,
6249 "%s: Delete STA with MAC::"
6250 "%02x:%02x:%02x:%02x:%02x:%02x",
6251 __func__,
6252 mac[0], mac[1], mac[2],
6253 mac[3], mac[4], mac[5]);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006254
6255 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
6256 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6257 {
6258 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
6259 hddLog(VOS_TRACE_LEVEL_INFO,
6260 "%s: STA removal failed for ::"
6261 "%02x:%02x:%02x:%02x:%02x:%02x",
6262 __func__,
6263 mac[0], mac[1], mac[2],
6264 mac[3], mac[4], mac[5]);
6265 return -ENOENT;
6266 }
6267
Jeff Johnson295189b2012-06-20 16:38:30 -07006268 }
6269 }
6270
6271 EXIT();
6272
6273 return 0;
6274}
6275
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006276#ifdef FEATURE_WLAN_TDLS
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006277static int wlan_hdd_tdls_add_station(struct wiphy *wiphy,
6278 struct net_device *dev, u8 *mac)
6279{
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006280 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6281 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006282 VOS_STATUS status;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006283
Jeff Johnsone7245742012-09-05 17:12:55 -07006284 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006285
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006286 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006287 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006288 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006289 "Invalid arguments");
6290 return -EINVAL;
6291 }
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006292 if (pHddCtx->isLogpInProgress)
6293 {
6294 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6295 "%s:LOGP in Progress. Ignore!!!", __func__);
6296 return -EBUSY;
6297 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006298
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006299 if (FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006300 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006301 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006302 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006303 "TDLS Disabled in INI OR not enabled in FW.\
6304 Cannot process TDLS commands \n");
6305 return -ENOTSUPP;
6306 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006307
6308 if (wlan_hdd_tdls_is_progress(mac, TRUE))
6309 {
6310 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6311 "%s: TDLS setup is ongoing. Request declined.",__func__);
6312 return -EPERM;
6313 }
6314
Lee Hoonkic1262f22013-01-24 21:59:00 -08006315 /* first to check if we reached to maximum supported TDLS peer.
6316 TODO: for now, return -EPERM looks working fine,
6317 but need to check if any other errno fit into this category.*/
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006318 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers())
Lee Hoonkic1262f22013-01-24 21:59:00 -08006319 {
6320 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6321 "%s: TDLS Max peer already connected. Request declined. \n",
6322 __func__);
6323 return -EPERM;
6324 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006325 else
6326 {
6327 hddTdlsPeer_t *pTdlsPeer;
6328 pTdlsPeer = wlan_hdd_tdls_find_peer(mac);
6329 if (pTdlsPeer && (eTDLS_LINK_CONNECTED == pTdlsPeer->link_status))
6330 {
6331 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6332 "%s: %02x:%02x:%02x:%02x:%02x:%02x already connected. Request declined.",
6333 __func__, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
6334 return -EPERM;
6335 }
6336 }
6337
6338 wlan_hdd_tdls_set_connection_progress(mac,TRUE);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006339
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006340 INIT_COMPLETION(pAdapter->tdls_add_station_comp);
6341
6342 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
6343 pAdapter->sessionId, mac);
6344
6345 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_add_station_comp,
6346 msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
6347
6348 if (!status)
6349 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006350 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006351 "%s: timeout waiting for tdls add station indication",
6352 __func__);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006353 wlan_hdd_tdls_set_connection_progress(mac, FALSE);
6354 return -EPERM;
6355 }
6356 if ( eHAL_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus)
6357 {
6358 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6359 "%s: Add Station is unsucessful", __func__);
6360 wlan_hdd_tdls_set_connection_progress(mac, FALSE);
6361 return -EPERM;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006362 }
6363
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006364 return 0;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006365}
6366#endif
6367
6368static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
6369 struct net_device *dev, u8 *mac, struct station_parameters *params)
6370{
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006371 int status = -EPERM;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006372#ifdef FEATURE_WLAN_TDLS
6373 u32 mask, set;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006374 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006375 mask = params->sta_flags_mask;
6376
6377 set = params->sta_flags_set;
6378
Lee Hoonkic1262f22013-01-24 21:59:00 -08006379 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6380 "%s: mask 0x%x set 0x%x\n",__func__, mask, set);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006381
6382 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6383 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006384 status = wlan_hdd_tdls_add_station(wiphy, dev, mac);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006385 }
6386 }
6387#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006388 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006389}
6390
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006391
6392#ifdef FEATURE_WLAN_LFR
6393static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006394 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006395{
6396#define MAX_PMKSAIDS_IN_CACHE 8
6397 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -07006398 static tANI_U32 i; // HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006399 tANI_U32 j=0;
6400 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6401 tHalHandle halHandle;
6402 eHalStatus result;
6403 tANI_U8 BSSIDMatched = 0;
6404
Jeff Johnsone7245742012-09-05 17:12:55 -07006405 ENTER();
6406
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006407 // Validate pAdapter
6408 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6409 {
6410 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6411 return -EINVAL;
6412 }
6413
6414 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6415 {
6416 hddLog( LOGE,
6417 "%s: Wlan Load/Unload is in progress", __func__);
6418 return -EBUSY;
6419 }
6420
6421 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6422 {
6423 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6424 "%s:LOGP in Progress. Ignore!!!", __func__);
6425 return -EAGAIN;
6426 }
6427
6428 // Retrieve halHandle
6429 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
6430
6431 for (j = 0; j < i; j++)
6432 {
6433 if(vos_mem_compare(PMKIDCache[j].BSSID,
6434 pmksa->bssid, WNI_CFG_BSSID_LEN))
6435 {
6436 /* BSSID matched previous entry. Overwrite it. */
6437 BSSIDMatched = 1;
6438 vos_mem_copy(PMKIDCache[j].BSSID,
6439 pmksa->bssid, WNI_CFG_BSSID_LEN);
6440 vos_mem_copy(PMKIDCache[j].PMKID,
6441 pmksa->pmkid,
6442 CSR_RSN_PMKID_SIZE);
6443 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006444 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006445 dump_bssid(pmksa->bssid);
6446 dump_pmkid(halHandle, pmksa->pmkid);
6447 break;
6448 }
6449 }
6450
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07006451 /* Check we compared all entries,if then take the first slot now */
6452 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
6453
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006454 if (!BSSIDMatched)
6455 {
6456 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
6457 vos_mem_copy(PMKIDCache[i].BSSID,
6458 pmksa->bssid, ETHER_ADDR_LEN);
6459 vos_mem_copy(PMKIDCache[i].PMKID,
6460 pmksa->pmkid,
6461 CSR_RSN_PMKID_SIZE);
6462 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006463 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006464 dump_bssid(pmksa->bssid);
6465 dump_pmkid(halHandle, pmksa->pmkid);
6466 // Increment the HDD Local Cache index
6467 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
6468 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
6469 }
6470
6471
6472 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
6473 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006474 // __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006475 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006476 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006477 // Finally set the PMKSA ID Cache in CSR
6478 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
6479 PMKIDCache,
6480 i );
6481 return 0;
6482}
6483
6484
6485static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006486 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006487{
Jeff Johnsone7245742012-09-05 17:12:55 -07006488 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006489 // TODO: Implement this later.
6490 return 0;
6491}
6492
6493static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
6494{
Jeff Johnsone7245742012-09-05 17:12:55 -07006495 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006496 // TODO: Implement this later.
6497 return 0;
6498}
6499#endif
6500
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006501#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6502static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
6503 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
6504{
6505 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6506 hdd_station_ctx_t *pHddStaCtx;
6507
6508 if (NULL == pAdapter)
6509 {
6510 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6511 return -ENODEV;
6512 }
6513
6514 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6515
6516 // Added for debug on reception of Re-assoc Req.
6517 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6518 {
6519 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
6520 ftie->ie_len);
6521 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
6522 }
6523
6524#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
6525 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
6526 ftie->ie_len);
6527#endif
6528
6529 // Pass the received FT IEs to SME
6530 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, ftie->ie,
6531 ftie->ie_len);
6532 return 0;
6533}
6534#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006535
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006536#ifdef FEATURE_WLAN_TDLS
6537static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
6538 u8 *peer, u8 action_code, u8 dialog_token,
6539 u16 status_code, const u8 *buf, size_t len)
6540{
6541
6542 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6543 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006544 u8 peerMac[6];
6545 VOS_STATUS status;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006546 int ret = 0;
Hoonki Leea34dd892013-02-05 22:56:02 -08006547 int responder;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006548
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006549 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006550 {
6551 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6552 "Invalid arguments");
6553 return -EINVAL;
6554 }
6555
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006556 if (pHddCtx->isLogpInProgress)
6557 {
6558 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6559 "%s:LOGP in Progress. Ignore!!!", __func__);
6560 return -EBUSY;
6561 }
6562
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006563 if (FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006564 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6565 {
6566 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6567 "TDLS Disabled in INI OR not enabled in FW.\
6568 Cannot process TDLS commands \n");
6569 return -ENOTSUPP;
6570 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006571
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006572 if (WLAN_IS_TDLS_SETUP_ACTION(action_code))
6573 {
6574 if (wlan_hdd_tdls_is_progress(peer, TRUE))
6575 {
6576 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6577 "%s: TDLS setup is ongoing. Request declined.", __func__);
6578 return -EPERM;
6579 }
6580 }
6581
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006582 if (SIR_MAC_TDLS_SETUP_REQ == action_code ||
6583 SIR_MAC_TDLS_SETUP_RSP == action_code )
Lee Hoonkic1262f22013-01-24 21:59:00 -08006584 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006585 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers())
Lee Hoonkic1262f22013-01-24 21:59:00 -08006586 {
6587 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
6588 we return error code at 'add_station()'. Hence we have this
6589 check again in addtion to add_station().
6590 Anyway, there is no hard to double-check. */
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006591 if (SIR_MAC_TDLS_SETUP_REQ == action_code)
Lee Hoonkic1262f22013-01-24 21:59:00 -08006592 {
6593 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6594 "%s: TDLS Max peer already connected. Request declined. \n",
6595 __func__);
6596 return -EPERM;
6597 }
6598 else
6599 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006600 /* maximum reached. tweak to send error code to peer and return
6601 error code to supplicant */
Lee Hoonkic1262f22013-01-24 21:59:00 -08006602 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
6603 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6604 "%s: TDLS Max peer already connected send response status %d \n",
6605 __func__,status_code);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006606 ret = -EPERM;
6607 /* fall through to send setup resp with failure status
6608 code */
Lee Hoonkic1262f22013-01-24 21:59:00 -08006609 }
6610 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006611 else
6612 {
6613 hddTdlsPeer_t *pTdlsPeer;
6614 pTdlsPeer = wlan_hdd_tdls_find_peer(peer);
6615 if (pTdlsPeer && (eTDLS_LINK_CONNECTED == pTdlsPeer->link_status))
6616 {
6617 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6618 "%s: %02x:%02x:%02x:%02x:%02x:%02x already connected. Request declined.",
6619 __func__, peer[0], peer[1], peer[2], peer[3], peer[4], peer[5]);
6620 return -EPERM;
6621 }
6622 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006623 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006624 vos_mem_copy(peerMac, peer, 6);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006625
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006626#ifdef WLAN_FEATURE_TDLS_DEBUG
6627 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6628 "%s: %02x:%02x:%02x:%02x:%02x:%02x) action %d, dialog_token %d status %d, len = %d",
6629 "tdls_mgmt", peer[0], peer[1], peer[2], peer[3], peer[4], peer[5],
6630 action_code, dialog_token, status_code, len);
6631#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006632
Hoonki Leea34dd892013-02-05 22:56:02 -08006633 /*Except teardown responder will not be used so just make 0*/
6634 responder = 0;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006635 if (SIR_MAC_TDLS_TEARDOWN == action_code)
Hoonki Leea34dd892013-02-05 22:56:02 -08006636 {
6637 responder = wlan_hdd_tdls_get_responder(peerMac);
Pervinder Singhb4638422013-03-04 22:51:36 -08006638 if (-1 == responder)
Hoonki Leea34dd892013-02-05 22:56:02 -08006639 {
6640 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6641 "%s: %02x:%02x:%02x:%02x:%02x:%02x) peer doesn't exist dialog_token %d status %d, len = %d",
6642 "tdls_mgmt", peer[0], peer[1], peer[2], peer[3], peer[4], peer[5],
6643 dialog_token, status_code, len);
6644 return -EPERM;
6645 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006646 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006647
Pervinder Singhb4638422013-03-04 22:51:36 -08006648 if (ret == 0 && /* if failure, don't need to set the progress bit */
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006649 (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
6650 wlan_hdd_tdls_set_connection_progress(peer, TRUE);
6651
6652 INIT_COMPLETION(pAdapter->tdls_mgmt_comp);
6653
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006654 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
Hoonki Leea34dd892013-02-05 22:56:02 -08006655 peerMac, action_code, dialog_token, status_code, (tANI_U8 *)buf, len, responder);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006656
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006657 if (VOS_STATUS_SUCCESS != status)
6658 {
6659 if(ret == 0 && /* if failure, don't need to set the progress bit */
6660 (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
6661 wlan_hdd_tdls_set_connection_progress(peer, FALSE);
6662
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006663 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6664 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006665 return -EPERM;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006666 }
6667
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006668 /* not block discovery request, as it is called from timer callback */
6669 if (SIR_MAC_TDLS_DIS_REQ != action_code)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006670 {
Pervinder Singhb4638422013-03-04 22:51:36 -08006671 long rc;
6672
6673 rc = wait_for_completion_interruptible_timeout(&pAdapter->tdls_mgmt_comp,
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006674 msecs_to_jiffies(WAIT_TIME_TDLS_MGMT));
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006675
Pervinder Singhb4638422013-03-04 22:51:36 -08006676 if ((rc <= 0) || (TRUE != pAdapter->mgmtTxCompletionStatus))
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006677 {
Pervinder Singhb4638422013-03-04 22:51:36 -08006678 if (ret == 0 && /* if failure, don't need to set the progress bit */
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006679 (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
6680 wlan_hdd_tdls_set_connection_progress(peer, FALSE);
6681
6682 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pervinder Singhb4638422013-03-04 22:51:36 -08006683 "%s: Mgmt Tx Completion failed status %ld TxCompletion %lu",
6684 __func__, rc, pAdapter->mgmtTxCompletionStatus);
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006685 return -EPERM;
6686 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006687 }
6688
6689 if (ret)
6690 return ret;
6691
Hoonki Leea34dd892013-02-05 22:56:02 -08006692 if (SIR_MAC_TDLS_SETUP_RSP == action_code)
6693 {
6694 wlan_hdd_tdls_set_responder(peerMac, TRUE);
6695 }
6696 else if (SIR_MAC_TDLS_SETUP_CNF == action_code)
6697 {
6698 wlan_hdd_tdls_set_responder(peerMac, FALSE);
6699 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006700
6701 return 0;
6702}
6703
6704static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
6705 u8 *peer, enum nl80211_tdls_operation oper)
6706{
6707 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6708 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006709#ifdef WLAN_FEATURE_TDLS_DEBUG
6710 const char *tdls_oper_str[]= {
6711 "NL80211_TDLS_DISCOVERY_REQ",
6712 "NL80211_TDLS_SETUP",
6713 "NL80211_TDLS_TEARDOWN",
6714 "NL80211_TDLS_ENABLE_LINK",
6715 "NL80211_TDLS_DISABLE_LINK",
6716 "NL80211_TDLS_UNKONW_OPER"};
6717#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006718
6719 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6720 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006721 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006722 "Invalid arguments");
6723 return -EINVAL;
6724 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006725
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006726 if (pHddCtx->isLogpInProgress)
6727 {
6728 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6729 "%s:LOGP in Progress. Ignore!!!", __func__);
6730 return -EBUSY;
6731 }
6732
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006733#ifdef WLAN_FEATURE_TDLS_DEBUG
6734 if((int)oper > 4)
6735 oper = 5;
6736
6737 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6738 "%s: %02x:%02x:%02x:%02x:%02x:%02x: %d (%s) ", "tdls_oper",
6739 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5], (int)oper,
6740 tdls_oper_str[(int)oper]);
6741#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006742
6743 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006744 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006745 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006746 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006747 "TDLS Disabled in INI OR not enabled in FW.\
6748 Cannot process TDLS commands \n");
6749 return -ENOTSUPP;
6750 }
6751
6752 switch (oper) {
6753 case NL80211_TDLS_ENABLE_LINK:
6754 {
Hoonki Lee387663d2013-02-05 18:08:43 -08006755 hddTdlsPeer_t *pTdlsPeer;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006756 VOS_STATUS status;
6757
6758 if (peer) {
Hoonki Lee387663d2013-02-05 18:08:43 -08006759 pTdlsPeer = wlan_hdd_tdls_find_peer(peer);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006760
6761 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
Hoonki Lee387663d2013-02-05 18:08:43 -08006762 "%s: TDLS_LINK_ENABLE %2x:%2x:%2x:%2x:%2x:%2x",
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006763 __func__, peer[0], peer[1],
6764 peer[2], peer[3],
6765 peer[4], peer[5] );
6766
Hoonki Lee387663d2013-02-05 18:08:43 -08006767 if ( NULL == pTdlsPeer ) {
6768 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_hdd_tdls_find_peer %2x:%2x:%2x:%2x:%2x:%2x failed",
6769 __func__, peer[0], peer[1],
6770 peer[2], peer[3],
6771 peer[4], peer[5] );
Hoonki Leef63df0d2013-01-16 19:29:14 -08006772 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006773 }
6774
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006775 if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status)
6776 {
6777 /* start TDLS client registration with TL */
6778 status = hdd_roamRegisterTDLSSTA( pAdapter, peer, pTdlsPeer->staId, pTdlsPeer->signature);
6779 wlan_hdd_tdls_increment_peer_count();
6780 wlan_hdd_tdls_set_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
6781 wlan_hdd_tdls_check_bmps(pHddCtx);
6782 wlan_hdd_tdls_set_connection_progress(peer, FALSE);
6783 }
Chilam NG571c65a2013-01-19 12:27:36 +05306784
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006785 } else {
6786 hddLog(VOS_TRACE_LEVEL_WARN, "wlan_hdd_cfg80211_add_key: peer NULL" );
6787 }
6788 }
6789 break;
6790 case NL80211_TDLS_DISABLE_LINK:
Lee Hoonkic1262f22013-01-24 21:59:00 -08006791 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006792 hddTdlsPeer_t *curr_peer = wlan_hdd_tdls_find_peer(peer);
6793
6794 if(NULL != curr_peer)
Lee Hoonkic1262f22013-01-24 21:59:00 -08006795 {
6796 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
6797 pAdapter->sessionId, peer );
Gopichand Nakkala901e8922013-03-04 23:45:58 -08006798 wlan_hdd_tdls_set_link_status(curr_peer, eTDLS_LINK_IDLE);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006799 curr_peer->isTDLSInProgress = FALSE;
Lee Hoonkic1262f22013-01-24 21:59:00 -08006800 }
6801 else
6802 {
6803 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6804 "%s: TDLS Peer Station doesn't exist \n",__func__);
6805 }
6806 return 0;
6807 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006808 case NL80211_TDLS_TEARDOWN:
6809 case NL80211_TDLS_SETUP:
6810 case NL80211_TDLS_DISCOVERY_REQ:
6811 /* We don't support in-driver setup/teardown/discovery */
6812 return -ENOTSUPP;
6813 default:
6814 return -ENOTSUPP;
6815 }
6816 return 0;
6817}
Chilam NG571c65a2013-01-19 12:27:36 +05306818
6819int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
6820 struct net_device *dev, u8 *peer)
6821{
6822 hddLog(VOS_TRACE_LEVEL_INFO, "tdls send discover req: %x %x %x %x %x %x",
6823 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5]);
6824
6825 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
6826 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
6827}
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006828#endif
6829
Jeff Johnson295189b2012-06-20 16:38:30 -07006830/* cfg80211_ops */
6831static struct cfg80211_ops wlan_hdd_cfg80211_ops =
6832{
6833 .add_virtual_intf = wlan_hdd_add_virtual_intf,
6834 .del_virtual_intf = wlan_hdd_del_virtual_intf,
6835 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
6836 .change_station = wlan_hdd_change_station,
6837#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
6838 .add_beacon = wlan_hdd_cfg80211_add_beacon,
6839 .del_beacon = wlan_hdd_cfg80211_del_beacon,
6840 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006841#else
6842 .start_ap = wlan_hdd_cfg80211_start_ap,
6843 .change_beacon = wlan_hdd_cfg80211_change_beacon,
6844 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07006845#endif
6846 .change_bss = wlan_hdd_cfg80211_change_bss,
6847 .add_key = wlan_hdd_cfg80211_add_key,
6848 .get_key = wlan_hdd_cfg80211_get_key,
6849 .del_key = wlan_hdd_cfg80211_del_key,
6850 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08006851#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07006852 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08006853#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006854 .scan = wlan_hdd_cfg80211_scan,
6855 .connect = wlan_hdd_cfg80211_connect,
6856 .disconnect = wlan_hdd_cfg80211_disconnect,
6857 .join_ibss = wlan_hdd_cfg80211_join_ibss,
6858 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
6859 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
6860 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
6861 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
Jeff Johnson295189b2012-06-20 16:38:30 -07006862 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
6863 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
6864 .mgmt_tx = wlan_hdd_action,
6865#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6866 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
6867 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
6868 .set_txq_params = wlan_hdd_set_txq_params,
6869#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006870 .get_station = wlan_hdd_cfg80211_get_station,
6871 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
6872 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006873 .add_station = wlan_hdd_cfg80211_add_station,
6874#ifdef FEATURE_WLAN_LFR
6875 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
6876 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
6877 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
6878#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006879#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6880 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
6881#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006882#ifdef FEATURE_WLAN_TDLS
6883 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
6884 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
6885#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006886};
6887