blob: 275407825d09cf7038a22928d858ad0342294b93 [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
74#ifdef CONFIG_CFG80211
75
76#include <linux/version.h>
77#include <linux/module.h>
78#include <linux/kernel.h>
79#include <linux/init.h>
80#include <linux/wireless.h>
81#include <wlan_hdd_includes.h>
82#include <net/arp.h>
83#include <net/cfg80211.h>
84#include <linux/wireless.h>
85#include <wlan_hdd_wowl.h>
86#include <aniGlobal.h>
87#include "ccmApi.h"
88#include "sirParams.h"
89#include "dot11f.h"
90#include "wlan_hdd_assoc.h"
91#include "wlan_hdd_wext.h"
92#include "sme_Api.h"
93#include "wlan_hdd_p2p.h"
94#include "wlan_hdd_cfg80211.h"
95#include "wlan_hdd_hostapd.h"
96#include "sapInternal.h"
97#include "wlan_hdd_softap_tx_rx.h"
98#include "wlan_hdd_main.h"
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +053099#include "wlan_hdd_assoc.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700100#ifdef WLAN_BTAMP_FEATURE
101#include "bap_hdd_misc.h"
102#endif
103#include <qc_sap_ioctl.h>
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800104#ifdef FEATURE_WLAN_TDLS
105#include "wlan_hdd_tdls.h"
106#endif
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +0530107#include "wlan_nv.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700108
109#define g_mode_rates_size (12)
110#define a_mode_rates_size (8)
111#define FREQ_BASE_80211G (2407)
112#define FREQ_BAND_DIFF_80211G (5)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700113#define MAX_SCAN_SSID 9
Jeff Johnson295189b2012-06-20 16:38:30 -0700114#define GET_IE_LEN_IN_BSS_DESC(lenInBss) ( lenInBss + sizeof(lenInBss) - \
115 ((int) OFFSET_OF( tSirBssDescription, ieFields)))
116
117#define HDD2GHZCHAN(freq, chan, flag) { \
118 .band = IEEE80211_BAND_2GHZ, \
119 .center_freq = (freq), \
120 .hw_value = (chan),\
121 .flags = (flag), \
122 .max_antenna_gain = 0 ,\
123 .max_power = 30, \
124}
125
126#define HDD5GHZCHAN(freq, chan, flag) { \
127 .band = IEEE80211_BAND_5GHZ, \
128 .center_freq = (freq), \
129 .hw_value = (chan),\
130 .flags = (flag), \
131 .max_antenna_gain = 0 ,\
132 .max_power = 30, \
133}
134
135#define HDD_G_MODE_RATETAB(rate, rate_id, flag)\
136{\
137 .bitrate = rate, \
138 .hw_value = rate_id, \
139 .flags = flag, \
140}
141
Lee Hoonkic1262f22013-01-24 21:59:00 -0800142#ifndef WLAN_FEATURE_TDLS_DEBUG
143#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_INFO
144#else
145#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_ERROR
146#endif
147
Jeff Johnson295189b2012-06-20 16:38:30 -0700148static const u32 hdd_cipher_suites[] =
149{
150 WLAN_CIPHER_SUITE_WEP40,
151 WLAN_CIPHER_SUITE_WEP104,
152 WLAN_CIPHER_SUITE_TKIP,
153#ifdef FEATURE_WLAN_CCX
154#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
155 WLAN_CIPHER_SUITE_KRK,
156 WLAN_CIPHER_SUITE_CCMP,
157#else
158 WLAN_CIPHER_SUITE_CCMP,
159#endif
160#ifdef FEATURE_WLAN_WAPI
161 WLAN_CIPHER_SUITE_SMS4,
162#endif
163};
164
165static inline int is_broadcast_ether_addr(const u8 *addr)
166{
167 return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&
168 (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
169}
170
171static struct ieee80211_channel hdd_channels_2_4_GHZ[] =
172{
173 HDD2GHZCHAN(2412, 1, 0) ,
174 HDD2GHZCHAN(2417, 2, 0) ,
175 HDD2GHZCHAN(2422, 3, 0) ,
176 HDD2GHZCHAN(2427, 4, 0) ,
177 HDD2GHZCHAN(2432, 5, 0) ,
178 HDD2GHZCHAN(2437, 6, 0) ,
179 HDD2GHZCHAN(2442, 7, 0) ,
180 HDD2GHZCHAN(2447, 8, 0) ,
181 HDD2GHZCHAN(2452, 9, 0) ,
182 HDD2GHZCHAN(2457, 10, 0) ,
183 HDD2GHZCHAN(2462, 11, 0) ,
184 HDD2GHZCHAN(2467, 12, 0) ,
185 HDD2GHZCHAN(2472, 13, 0) ,
186 HDD2GHZCHAN(2484, 14, 0) ,
187};
188
189#ifdef WLAN_FEATURE_P2P
190static struct ieee80211_channel hdd_social_channels_2_4_GHZ[] =
191{
192 HDD2GHZCHAN(2412, 1, 0) ,
193 HDD2GHZCHAN(2437, 6, 0) ,
194 HDD2GHZCHAN(2462, 11, 0) ,
195};
196#endif
197
198static struct ieee80211_channel hdd_channels_5_GHZ[] =
199{
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700200 HDD5GHZCHAN(4920, 240, 0) ,
201 HDD5GHZCHAN(4940, 244, 0) ,
202 HDD5GHZCHAN(4960, 248, 0) ,
203 HDD5GHZCHAN(4980, 252, 0) ,
204 HDD5GHZCHAN(5040, 208, 0) ,
205 HDD5GHZCHAN(5060, 212, 0) ,
206 HDD5GHZCHAN(5080, 216, 0) ,
Jeff Johnson295189b2012-06-20 16:38:30 -0700207 HDD5GHZCHAN(5180, 36, 0) ,
208 HDD5GHZCHAN(5200, 40, 0) ,
209 HDD5GHZCHAN(5220, 44, 0) ,
210 HDD5GHZCHAN(5240, 48, 0) ,
211 HDD5GHZCHAN(5260, 52, 0) ,
212 HDD5GHZCHAN(5280, 56, 0) ,
213 HDD5GHZCHAN(5300, 60, 0) ,
214 HDD5GHZCHAN(5320, 64, 0) ,
215 HDD5GHZCHAN(5500,100, 0) ,
216 HDD5GHZCHAN(5520,104, 0) ,
217 HDD5GHZCHAN(5540,108, 0) ,
218 HDD5GHZCHAN(5560,112, 0) ,
219 HDD5GHZCHAN(5580,116, 0) ,
220 HDD5GHZCHAN(5600,120, 0) ,
221 HDD5GHZCHAN(5620,124, 0) ,
222 HDD5GHZCHAN(5640,128, 0) ,
223 HDD5GHZCHAN(5660,132, 0) ,
224 HDD5GHZCHAN(5680,136, 0) ,
225 HDD5GHZCHAN(5700,140, 0) ,
226 HDD5GHZCHAN(5745,149, 0) ,
227 HDD5GHZCHAN(5765,153, 0) ,
228 HDD5GHZCHAN(5785,157, 0) ,
229 HDD5GHZCHAN(5805,161, 0) ,
230 HDD5GHZCHAN(5825,165, 0) ,
231};
232
233static struct ieee80211_rate g_mode_rates[] =
234{
235 HDD_G_MODE_RATETAB(10, 0x1, 0),
236 HDD_G_MODE_RATETAB(20, 0x2, 0),
237 HDD_G_MODE_RATETAB(55, 0x4, 0),
238 HDD_G_MODE_RATETAB(110, 0x8, 0),
239 HDD_G_MODE_RATETAB(60, 0x10, 0),
240 HDD_G_MODE_RATETAB(90, 0x20, 0),
241 HDD_G_MODE_RATETAB(120, 0x40, 0),
242 HDD_G_MODE_RATETAB(180, 0x80, 0),
243 HDD_G_MODE_RATETAB(240, 0x100, 0),
244 HDD_G_MODE_RATETAB(360, 0x200, 0),
245 HDD_G_MODE_RATETAB(480, 0x400, 0),
246 HDD_G_MODE_RATETAB(540, 0x800, 0),
247};
248
249static struct ieee80211_rate a_mode_rates[] =
250{
251 HDD_G_MODE_RATETAB(60, 0x10, 0),
252 HDD_G_MODE_RATETAB(90, 0x20, 0),
253 HDD_G_MODE_RATETAB(120, 0x40, 0),
254 HDD_G_MODE_RATETAB(180, 0x80, 0),
255 HDD_G_MODE_RATETAB(240, 0x100, 0),
256 HDD_G_MODE_RATETAB(360, 0x200, 0),
257 HDD_G_MODE_RATETAB(480, 0x400, 0),
258 HDD_G_MODE_RATETAB(540, 0x800, 0),
259};
260
261static struct ieee80211_supported_band wlan_hdd_band_2_4_GHZ =
262{
263 .channels = hdd_channels_2_4_GHZ,
264 .n_channels = ARRAY_SIZE(hdd_channels_2_4_GHZ),
265 .band = IEEE80211_BAND_2GHZ,
266 .bitrates = g_mode_rates,
267 .n_bitrates = g_mode_rates_size,
268 .ht_cap.ht_supported = 1,
269 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
270 | IEEE80211_HT_CAP_GRN_FLD
271 | IEEE80211_HT_CAP_DSSSCCK40
272 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
273 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
274 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
275 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
276 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
277 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
278};
279
280#ifdef WLAN_FEATURE_P2P
281static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_GHZ =
282{
283 .channels = hdd_social_channels_2_4_GHZ,
284 .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_GHZ),
285 .band = IEEE80211_BAND_2GHZ,
286 .bitrates = g_mode_rates,
287 .n_bitrates = g_mode_rates_size,
288 .ht_cap.ht_supported = 1,
289 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
290 | IEEE80211_HT_CAP_GRN_FLD
291 | IEEE80211_HT_CAP_DSSSCCK40
292 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
293 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
294 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
295 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
296 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
297 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
298};
299#endif
300
301static struct ieee80211_supported_band wlan_hdd_band_5_GHZ =
302{
303 .channels = hdd_channels_5_GHZ,
304 .n_channels = ARRAY_SIZE(hdd_channels_5_GHZ),
305 .band = IEEE80211_BAND_5GHZ,
306 .bitrates = a_mode_rates,
307 .n_bitrates = a_mode_rates_size,
308 .ht_cap.ht_supported = 1,
309 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
310 | IEEE80211_HT_CAP_GRN_FLD
311 | IEEE80211_HT_CAP_DSSSCCK40
312 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
313 | IEEE80211_HT_CAP_SGI_40
314 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
315 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
316 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
317 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
318 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
319 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
320};
321
322/* This structure contain information what kind of frame are expected in
323 TX/RX direction for each kind of interface */
324static const struct ieee80211_txrx_stypes
325wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
326 [NL80211_IFTYPE_STATION] = {
327 .tx = 0xffff,
328 .rx = BIT(SIR_MAC_MGMT_ACTION) |
329 BIT(SIR_MAC_MGMT_PROBE_REQ),
330 },
331 [NL80211_IFTYPE_AP] = {
332 .tx = 0xffff,
333 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
334 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
335 BIT(SIR_MAC_MGMT_PROBE_REQ) |
336 BIT(SIR_MAC_MGMT_DISASSOC) |
337 BIT(SIR_MAC_MGMT_AUTH) |
338 BIT(SIR_MAC_MGMT_DEAUTH) |
339 BIT(SIR_MAC_MGMT_ACTION),
340 },
341#ifdef WLAN_FEATURE_P2P
342 [NL80211_IFTYPE_P2P_CLIENT] = {
343 .tx = 0xffff,
344 .rx = BIT(SIR_MAC_MGMT_ACTION) |
345 BIT(SIR_MAC_MGMT_PROBE_REQ),
346 },
347 [NL80211_IFTYPE_P2P_GO] = {
348 /* This is also same as for SoftAP */
349 .tx = 0xffff,
350 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
351 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
352 BIT(SIR_MAC_MGMT_PROBE_REQ) |
353 BIT(SIR_MAC_MGMT_DISASSOC) |
354 BIT(SIR_MAC_MGMT_AUTH) |
355 BIT(SIR_MAC_MGMT_DEAUTH) |
356 BIT(SIR_MAC_MGMT_ACTION),
357 },
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800358#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700359};
360
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800361#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
362#ifdef WLAN_FEATURE_P2P
363static const struct ieee80211_iface_limit
364wlan_hdd_iface_limit[] = {
365 {
Sunil Ravia72c3992013-01-31 06:12:22 -0800366 /* max = 3 ; Our driver create two interfaces during driver init
367 * wlan0 and p2p0 interfaces. p2p0 is considered as station
368 * interface until a group is formed. In JB architecture, once the
369 * group is formed, interface type of p2p0 is changed to P2P GO or
370 * Client.
371 * When supplicant remove the group, it first issue a set interface
372 * cmd to change the mode back to Station. In JB this works fine as
373 * we advertize two station type interface during driver init.
374 * Some vendors create separate interface for P2P GO/Client,
375 * after group formation(Third one). But while group remove
376 * supplicant first tries to change the mode(3rd interface) to STATION
377 * But as we advertized only two sta type interfaces nl80211 was
378 * returning error for the third one which was leading to failure in
379 * delete interface. Ideally while removing the group, supplicant
380 * should not try to change the 3rd interface mode to Station type.
381 * Till we get a fix in wpa_supplicant, we advertize max STA
382 * interface type to 3
383 */
384 .max = 3,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800385 .types = BIT(NL80211_IFTYPE_STATION),
386 },
387 {
388 .max = 1,
389 .types = BIT(NL80211_IFTYPE_AP),
390 },
391 {
392 .max = 1,
393 .types = BIT(NL80211_IFTYPE_P2P_GO) |
394 BIT(NL80211_IFTYPE_P2P_CLIENT),
395 },
396};
397
398/* By default, only single channel concurrency is allowed */
399static struct ieee80211_iface_combination
400wlan_hdd_iface_combination = {
401 .limits = wlan_hdd_iface_limit,
402 .num_different_channels = 1,
Sunil Ravia72c3992013-01-31 06:12:22 -0800403 /*
404 * max = WLAN_MAX_INTERFACES ; JellyBean architecture creates wlan0
405 * and p2p0 interfaces during driver init
406 * Some vendors create separate interface for P2P operations.
407 * wlan0: STA interface
408 * p2p0: P2P Device interface, action frames goes
409 * through this interface.
410 * p2p-xx: P2P interface, After GO negotiation this interface is
411 * created for p2p operations(GO/CLIENT interface).
412 */
413 .max_interfaces = WLAN_MAX_INTERFACES,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800414 .n_limits = ARRAY_SIZE(wlan_hdd_iface_limit),
415 .beacon_int_infra_match = false,
416};
417#endif
418#endif
419
Jeff Johnson295189b2012-06-20 16:38:30 -0700420static struct cfg80211_ops wlan_hdd_cfg80211_ops;
421
422/* Data rate 100KBPS based on IE Index */
423struct index_data_rate_type
424{
425 v_U8_t beacon_rate_index;
426 v_U16_t supported_rate[4];
427};
428
429/* 11B, 11G Rate table include Basic rate and Extended rate
430 The IDX field is the rate index
431 The HI field is the rate when RSSI is strong or being ignored
432 (in this case we report actual rate)
433 The MID field is the rate when RSSI is moderate
434 (in this case we cap 11b rates at 5.5 and 11g rates at 24)
435 The LO field is the rate when RSSI is low
436 (in this case we don't report rates, actual current rate used)
437 */
438static const struct
439{
440 v_U8_t beacon_rate_index;
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700441 v_U16_t supported_rate[4];
Jeff Johnson295189b2012-06-20 16:38:30 -0700442} supported_data_rate[] =
443{
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700444/* IDX HI HM LM LO (RSSI-based index */
445 {2, { 10, 10, 10, 0}},
446 {4, { 20, 20, 10, 0}},
447 {11, { 55, 20, 10, 0}},
448 {12, { 60, 55, 20, 0}},
449 {18, { 90, 55, 20, 0}},
450 {22, {110, 55, 20, 0}},
451 {24, {120, 90, 60, 0}},
452 {36, {180, 120, 60, 0}},
453 {44, {220, 180, 60, 0}},
454 {48, {240, 180, 90, 0}},
455 {66, {330, 180, 90, 0}},
456 {72, {360, 240, 90, 0}},
457 {96, {480, 240, 120, 0}},
458 {108, {540, 240, 120, 0}}
Jeff Johnson295189b2012-06-20 16:38:30 -0700459};
460
461/* MCS Based rate table */
462static struct index_data_rate_type supported_mcs_rate[] =
463{
464/* MCS L20 L40 S20 S40 */
465 {0, {65, 135, 72, 150}},
466 {1, {130, 270, 144, 300}},
467 {2, {195, 405, 217, 450}},
468 {3, {260, 540, 289, 600}},
469 {4, {390, 810, 433, 900}},
470 {5, {520, 1080, 578, 1200}},
471 {6, {585, 1215, 650, 1350}},
472 {7, {650, 1350, 722, 1500}}
473};
474
475extern struct net_device_ops net_ops_struct;
476
477/*
478 * FUNCTION: wlan_hdd_cfg80211_init
479 * This function is called by hdd_wlan_startup()
480 * during initialization.
481 * This function is used to initialize and register wiphy structure.
482 */
483struct wiphy *wlan_hdd_cfg80211_init(int priv_size)
484{
485 struct wiphy *wiphy;
486 ENTER();
487
488 /*
489 * Create wiphy device
490 */
491 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
492
493 if (!wiphy)
494 {
495 /* Print error and jump into err label and free the memory */
496 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__);
497 return NULL;
498 }
499
500 return wiphy;
501}
502
503/*
504 * FUNCTION: wlan_hdd_cfg80211_update_band
505 * This function is called from the supplicant through a
506 * private ioctl to change the band value
507 */
508int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
509{
Jeff Johnsone7245742012-09-05 17:12:55 -0700510 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700511 switch(eBand)
512 {
513 case eCSR_BAND_24:
514 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
515 wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
516 break;
517 case eCSR_BAND_5G:
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700518#ifdef WLAN_FEATURE_P2P
519 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
520#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700521 wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700522#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700523 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
524 break;
525 case eCSR_BAND_ALL:
526 default:
527 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
528 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
529 }
530 return 0;
531}
532/*
533 * FUNCTION: wlan_hdd_cfg80211_init
534 * This function is called by hdd_wlan_startup()
535 * during initialization.
536 * This function is used to initialize and register wiphy structure.
537 */
538int wlan_hdd_cfg80211_register(struct device *dev,
539 struct wiphy *wiphy,
540 hdd_config_t *pCfg
541 )
542{
Jeff Johnsone7245742012-09-05 17:12:55 -0700543 ENTER();
544
Jeff Johnson295189b2012-06-20 16:38:30 -0700545 /* Now bind the underlying wlan device with wiphy */
546 set_wiphy_dev(wiphy, dev);
547
548 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
549
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700550 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700551
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700552#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700553 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
554 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
555 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
Jeff Johnsone7245742012-09-05 17:12:55 -0700556 | WIPHY_FLAG_OFFCHAN_TX;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700557#endif
James Zmuda77fb5ae2013-01-29 08:00:17 -0800558#ifdef FEATURE_WLAN_LFR
559 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
560#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800561#ifdef FEATURE_WLAN_TDLS
562 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
563 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
564#endif
565
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700566 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
567 driver can still register regulatory callback and
568 it will get CRDA setting in wiphy->band[], but
569 driver need to determine what to do with both
570 regulatory settings */
571 wiphy->reg_notifier = wlan_hdd_crda_reg_notifier;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700572
Jeff Johnson295189b2012-06-20 16:38:30 -0700573 wiphy->max_scan_ssids = MAX_SCAN_SSID;
574
575 wiphy->max_scan_ie_len = 200 ; //TODO: define a macro
576
577 /* Supports STATION & AD-HOC modes right now */
578 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
579 | BIT(NL80211_IFTYPE_ADHOC)
580#ifdef WLAN_FEATURE_P2P
581 | BIT(NL80211_IFTYPE_P2P_CLIENT)
582 | BIT(NL80211_IFTYPE_P2P_GO)
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800583#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700584 | BIT(NL80211_IFTYPE_AP);
585
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800586#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
587#ifdef WLAN_FEATURE_P2P
588 if( pCfg->enableMCC )
589 {
590 /* Currently, supports up to two channels */
591 wlan_hdd_iface_combination.num_different_channels = 2;
592
593 if( !pCfg->allowMCCGODiffBI )
594 wlan_hdd_iface_combination.beacon_int_infra_match = true;
595
596 }
597 wiphy->iface_combinations = &wlan_hdd_iface_combination;
598 wiphy->n_iface_combinations = 1;
599#endif
600#endif
601
Jeff Johnson295189b2012-06-20 16:38:30 -0700602 /* Before registering we need to update the ht capabilitied based
603 * on ini values*/
604 if( !pCfg->ShortGI20MhzEnable )
605 {
606 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
607 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
608 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
609 }
610
611 if( !pCfg->ShortGI40MhzEnable )
612 {
613 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
614 }
615
616 if( !pCfg->nChannelBondingMode5GHz )
617 {
618 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
619 }
620
621 /*Initialize band capability*/
622 switch(pCfg->nBandCapability)
623 {
624 case eCSR_BAND_24:
625 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
626 break;
627 case eCSR_BAND_5G:
628#ifdef WLAN_FEATURE_P2P
629 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
630#endif
631 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
632 break;
633 case eCSR_BAND_ALL:
634 default:
635 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
636 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
637 }
638 /*Initialise the supported cipher suite details*/
639 wiphy->cipher_suites = hdd_cipher_suites;
640 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
641
642 /*signal strength in mBm (100*dBm) */
643 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
644
645#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
646#ifdef WLAN_FEATURE_P2P
647 wiphy->max_remain_on_channel_duration = 1000;
648#endif
649#endif
650
651 /* Register our wiphy dev with cfg80211 */
652 if (0 > wiphy_register(wiphy))
653 {
654 /* print eror */
655 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
656 return -EIO;
657 }
658
659 EXIT();
660 return 0;
661}
662
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700663/* In this function we will try to get default country code from crda.
664 If the gCrdaDefaultCountryCode is configured in ini file,
665 we will try to call user space crda to get the regulatory settings for
666 that country. We will timeout if we can't get it from crda.
667 It's called by hdd_wlan_startup() after wlan_hdd_cfg80211_register.
668*/
669int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg)
670{
671 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
672 if (memcmp(pCfg->crdaDefaultCountryCode,
673 CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) != 0)
674 {
675 init_completion(&pHddCtx->driver_crda_req);
676 regulatory_hint(wiphy, pCfg->crdaDefaultCountryCode);
677 wait_for_completion_interruptible_timeout(&pHddCtx->driver_crda_req,
678 CRDA_WAIT_TIME);
679 }
680 return 0;
681}
682
Jeff Johnson295189b2012-06-20 16:38:30 -0700683/* In this function we will do all post VOS start initialization.
684 In this function we will register for all frame in which supplicant
685 is interested.
686*/
687void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
688{
689#ifdef WLAN_FEATURE_P2P
690 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
691 /* Register for all P2P action, public action etc frames */
692 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
693
Jeff Johnsone7245742012-09-05 17:12:55 -0700694 ENTER();
695
Jeff Johnson295189b2012-06-20 16:38:30 -0700696 /* Right now we are registering these frame when driver is getting
697 initialized. Once we will move to 2.6.37 kernel, in which we have
698 frame register ops, we will move this code as a part of that */
699 /* GAS Initial Request */
700 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
701 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
702
703 /* GAS Initial Response */
704 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
705 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
706
707 /* GAS Comeback Request */
708 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
709 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
710
711 /* GAS Comeback Response */
712 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
713 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
714
715 /* P2P Public Action */
716 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
717 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
718 P2P_PUBLIC_ACTION_FRAME_SIZE );
719
720 /* P2P Action */
721 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
722 (v_U8_t*)P2P_ACTION_FRAME,
723 P2P_ACTION_FRAME_SIZE );
724#endif /* WLAN_FEATURE_P2P */
725}
726
727void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
728{
729#ifdef WLAN_FEATURE_P2P
730 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
731 /* Register for all P2P action, public action etc frames */
732 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
733
Jeff Johnsone7245742012-09-05 17:12:55 -0700734 ENTER();
735
Jeff Johnson295189b2012-06-20 16:38:30 -0700736 /* Right now we are registering these frame when driver is getting
737 initialized. Once we will move to 2.6.37 kernel, in which we have
738 frame register ops, we will move this code as a part of that */
739 /* GAS Initial Request */
740
741 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
742 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
743
744 /* GAS Initial Response */
745 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
746 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
747
748 /* GAS Comeback Request */
749 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
750 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
751
752 /* GAS Comeback Response */
753 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
754 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
755
756 /* P2P Public Action */
757 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
758 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
759 P2P_PUBLIC_ACTION_FRAME_SIZE );
760
761 /* P2P Action */
762 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
763 (v_U8_t*)P2P_ACTION_FRAME,
764 P2P_ACTION_FRAME_SIZE );
765#endif /* WLAN_FEATURE_P2P */
766}
767
768#ifdef FEATURE_WLAN_WAPI
769void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
770 const u8 *mac_addr, u8 *key , int key_Len)
771{
772 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
773 tCsrRoamSetKey setKey;
774 v_BOOL_t isConnected = TRUE;
775 int status = 0;
776 v_U32_t roamId= 0xFF;
777 tANI_U8 *pKeyPtr = NULL;
778 int n = 0;
779
780 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
781 __func__,pAdapter->device_mode);
782
Gopichand Nakkalae7480202013-02-11 15:24:22 +0530783 vos_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Jeff Johnson295189b2012-06-20 16:38:30 -0700784 setKey.keyId = key_index; // Store Key ID
785 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
786 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
787 setKey.paeRole = 0 ; // the PAE role
788 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
789 {
790 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
791 }
792 else
793 {
794 isConnected = hdd_connIsConnected(pHddStaCtx);
795 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
796 }
797 setKey.keyLength = key_Len;
798 pKeyPtr = setKey.Key;
799 memcpy( pKeyPtr, key, key_Len);
800
801 hddLog(VOS_TRACE_LEVEL_INFO,"\n%s: WAPI KEY LENGTH:0x%04x",
802 __func__, key_Len);
803 for (n = 0 ; n < key_Len; n++)
804 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
805 __func__,n,setKey.Key[n]);
806
807 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
808 if ( isConnected )
809 {
810 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
811 pAdapter->sessionId, &setKey, &roamId );
812 }
813 if ( status != 0 )
814 {
815 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
816 "[%4d] sme_RoamSetKey returned ERROR status= %d",
817 __LINE__, status );
818 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
819 }
820}
821#endif /* FEATURE_WLAN_WAPI*/
822
823#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
824int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
825 beacon_data_t **ppBeacon,
826 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700827#else
828int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
829 beacon_data_t **ppBeacon,
830 struct cfg80211_beacon_data *params,
831 int dtim_period)
832#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700833{
834 int size;
835 beacon_data_t *beacon = NULL;
836 beacon_data_t *old = NULL;
837 int head_len,tail_len;
838
Jeff Johnsone7245742012-09-05 17:12:55 -0700839 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700840 if (params->head && !params->head_len)
841 return -EINVAL;
842
843 old = pAdapter->sessionCtx.ap.beacon;
844
845 if (!params->head && !old)
846 return -EINVAL;
847
848 if (params->tail && !params->tail_len)
849 return -EINVAL;
850
851#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
852 /* Kernel 3.0 is not updating dtim_period for set beacon */
853 if (!params->dtim_period)
854 return -EINVAL;
855#endif
856
857 if(params->head)
858 head_len = params->head_len;
859 else
860 head_len = old->head_len;
861
862 if(params->tail || !old)
863 tail_len = params->tail_len;
864 else
865 tail_len = old->tail_len;
866
867 size = sizeof(beacon_data_t) + head_len + tail_len;
868
869 beacon = kzalloc(size, GFP_KERNEL);
870
871 if( beacon == NULL )
872 return -ENOMEM;
873
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700874#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700875 if(params->dtim_period || !old )
876 beacon->dtim_period = params->dtim_period;
877 else
878 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700879#else
880 if(dtim_period || !old )
881 beacon->dtim_period = dtim_period;
882 else
883 beacon->dtim_period = old->dtim_period;
884#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700885
886 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
887 beacon->tail = beacon->head + head_len;
888 beacon->head_len = head_len;
889 beacon->tail_len = tail_len;
890
891 if(params->head) {
892 memcpy (beacon->head,params->head,beacon->head_len);
893 }
894 else {
895 if(old)
896 memcpy (beacon->head,old->head,beacon->head_len);
897 }
898
899 if(params->tail) {
900 memcpy (beacon->tail,params->tail,beacon->tail_len);
901 }
902 else {
903 if(old)
904 memcpy (beacon->tail,old->tail,beacon->tail_len);
905 }
906
907 *ppBeacon = beacon;
908
909 kfree(old);
910
911 return 0;
912
913}
Jeff Johnson295189b2012-06-20 16:38:30 -0700914
915v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
916{
917 int left = length;
918 v_U8_t *ptr = pIes;
919 v_U8_t elem_id,elem_len;
920
921 while(left >= 2)
922 {
923 elem_id = ptr[0];
924 elem_len = ptr[1];
925 left -= 2;
926 if(elem_len > left)
927 {
928 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700929 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -0700930 eid,elem_len,left);
931 return NULL;
932 }
933 if (elem_id == eid)
934 {
935 return ptr;
936 }
937
938 left -= elem_len;
939 ptr += (elem_len + 2);
940 }
941 return NULL;
942}
943
Jeff Johnson295189b2012-06-20 16:38:30 -0700944/* Check if rate is 11g rate or not */
945static int wlan_hdd_rate_is_11g(u8 rate)
946{
947 u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 104}; /* actual rate * 2 */
948 u8 i;
949 for (i = 0; i < 8; i++)
950 {
951 if(rate == gRateArray[i])
952 return TRUE;
953 }
954 return FALSE;
955}
956
957/* Check for 11g rate and set proper 11g only mode */
958static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
959 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
960{
961 u8 i, num_rates = pIe[0];
962
963 pIe += 1;
964 for ( i = 0; i < num_rates; i++)
965 {
966 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
967 {
968 /* If rate set have 11g rate than change the mode to 11G */
969 *pSapHw_mode = eSAP_DOT11_MODE_11g;
970 if (pIe[i] & BASIC_RATE_MASK)
971 {
972 /* If we have 11g rate as basic rate, it means mode
973 is 11g only mode.
974 */
975 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
976 *pCheckRatesfor11g = FALSE;
977 }
978 }
979 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
980 {
981 *require_ht = TRUE;
982 }
983 }
984 return;
985}
986
987static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
988{
989 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
990 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
991 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
992 u8 checkRatesfor11g = TRUE;
993 u8 require_ht = FALSE;
994 u8 *pIe=NULL;
995
996 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
997
998 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
999 pBeacon->head_len, WLAN_EID_SUPP_RATES);
1000 if (pIe != NULL)
1001 {
1002 pIe += 1;
1003 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1004 &pConfig->SapHw_mode);
1005 }
1006
1007 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1008 WLAN_EID_EXT_SUPP_RATES);
1009 if (pIe != NULL)
1010 {
1011
1012 pIe += 1;
1013 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1014 &pConfig->SapHw_mode);
1015 }
1016
1017 if( pConfig->channel > 14 )
1018 {
1019 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
1020 }
1021
1022 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1023 WLAN_EID_HT_CAPABILITY);
1024
1025 if(pIe)
1026 {
1027 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
1028 if(require_ht)
1029 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
1030 }
1031}
1032
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001033#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001034static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1035 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001036#else
1037static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1038 struct cfg80211_beacon_data *params)
1039#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001040{
1041 v_U8_t *genie;
1042 v_U8_t total_ielen = 0, ielen = 0;
1043 v_U8_t *pIe = NULL;
1044 v_U8_t addIE[1] = {0};
1045 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
Jeff Johnsone7245742012-09-05 17:12:55 -07001046 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001047
1048 genie = vos_mem_malloc(MAX_GENIE_LEN);
1049
1050 if(genie == NULL) {
1051
1052 return -ENOMEM;
1053 }
1054
1055 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1056
1057 if(pIe)
1058 {
1059 /*Copy the wps IE*/
1060 ielen = pIe[1] + 2;
1061 if( ielen <=MAX_GENIE_LEN)
1062 {
1063 vos_mem_copy(genie, pIe, ielen);
1064 }
1065 else
1066 {
1067 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001068 ret = -EINVAL;
1069 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001070 }
1071 total_ielen = ielen;
1072 }
1073
1074#ifdef WLAN_FEATURE_WFD
1075 pIe = wlan_hdd_get_wfd_ie_ptr(pBeacon->tail,pBeacon->tail_len);
1076
1077 if(pIe)
1078 {
1079 ielen = pIe[1] + 2;
1080 if(total_ielen + ielen <= MAX_GENIE_LEN) {
1081 vos_mem_copy(&genie[total_ielen],pIe,(pIe[1] + 2));
1082 }
1083 else {
1084 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie + P2p Ie + Wfd Ie Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001085 ret = -EINVAL;
1086 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001087 }
1088 total_ielen += ielen;
1089 }
1090#endif
1091
1092#ifdef WLAN_FEATURE_P2P
1093 pIe = wlan_hdd_get_p2p_ie_ptr(pBeacon->tail,pBeacon->tail_len);
1094
1095 if(pIe)
1096 {
1097 ielen = pIe[1] + 2;
1098 if(total_ielen + ielen <= MAX_GENIE_LEN)
1099 {
1100 vos_mem_copy(&genie[total_ielen], pIe, (pIe[1] + 2));
1101 }
1102 else
1103 {
1104 hddLog( VOS_TRACE_LEVEL_ERROR,
1105 "**Wps Ie+ P2pIE Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001106 ret = -EINVAL;
1107 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001108 }
1109 total_ielen += ielen;
1110 }
1111#endif
1112
1113 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1114 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1115 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1116 {
1117 hddLog(LOGE,
1118 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001119 ret = -EINVAL;
1120 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001121 }
1122
1123 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1124 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1125 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1126 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1127 ==eHAL_STATUS_FAILURE)
1128 {
1129 hddLog(LOGE,
1130 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001131 ret = -EINVAL;
1132 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001133 }
1134
1135 // Added for ProResp IE
1136 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1137 {
1138 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1139 u8 probe_rsp_ie_len[3] = {0};
1140 u8 counter = 0;
1141 /* Check Probe Resp Length if it is greater then 255 then Store
1142 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1143 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1144 Store More then 255 bytes into One Variable.
1145 */
1146 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1147 {
1148 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1149 {
1150 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1151 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1152 }
1153 else
1154 {
1155 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1156 rem_probe_resp_ie_len = 0;
1157 }
1158 }
1159
1160 rem_probe_resp_ie_len = 0;
1161
1162 if (probe_rsp_ie_len[0] > 0)
1163 {
1164 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1165 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1166 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1167 probe_rsp_ie_len[0], NULL,
1168 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1169 {
1170 hddLog(LOGE,
1171 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001172 ret = -EINVAL;
1173 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001174 }
1175 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1176 }
1177
1178 if (probe_rsp_ie_len[1] > 0)
1179 {
1180 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1181 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1182 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1183 probe_rsp_ie_len[1], NULL,
1184 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1185 {
1186 hddLog(LOGE,
1187 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001188 ret = -EINVAL;
1189 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001190 }
1191 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1192 }
1193
1194 if (probe_rsp_ie_len[2] > 0)
1195 {
1196 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1197 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1198 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1199 probe_rsp_ie_len[2], NULL,
1200 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1201 {
1202 hddLog(LOGE,
1203 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001204 ret = -EINVAL;
1205 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001206 }
1207 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1208 }
1209
1210 if (probe_rsp_ie_len[1] == 0 )
1211 {
1212 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1213 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1214 eANI_BOOLEAN_FALSE) )
1215 {
1216 hddLog(LOGE,
1217 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1218 }
1219 }
1220
1221 if (probe_rsp_ie_len[2] == 0 )
1222 {
1223 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1224 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1225 eANI_BOOLEAN_FALSE) )
1226 {
1227 hddLog(LOGE,
1228 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1229 }
1230 }
1231
1232 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1233 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1234 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1235 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1236 == eHAL_STATUS_FAILURE)
1237 {
1238 hddLog(LOGE,
1239 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001240 ret = -EINVAL;
1241 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001242 }
1243 }
1244 else
1245 {
1246 // Reset WNI_CFG_PROBE_RSP Flags
1247 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1248
1249 hddLog(VOS_TRACE_LEVEL_INFO,
1250 "%s: No Probe Response IE received in set beacon",
1251 __func__);
1252 }
1253
1254 // Added for AssocResp IE
1255 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1256 {
1257 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1258 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1259 params->assocresp_ies_len, NULL,
1260 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1261 {
1262 hddLog(LOGE,
1263 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001264 ret = -EINVAL;
1265 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001266 }
1267
1268 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1269 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1270 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1271 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1272 == eHAL_STATUS_FAILURE)
1273 {
1274 hddLog(LOGE,
1275 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001276 ret = -EINVAL;
1277 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001278 }
1279 }
1280 else
1281 {
1282 hddLog(VOS_TRACE_LEVEL_INFO,
1283 "%s: No Assoc Response IE received in set beacon",
1284 __func__);
1285
1286 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1287 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1288 eANI_BOOLEAN_FALSE) )
1289 {
1290 hddLog(LOGE,
1291 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1292 }
1293 }
1294
Jeff Johnsone7245742012-09-05 17:12:55 -07001295done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001296 vos_mem_free(genie);
1297 return 0;
1298}
Jeff Johnson295189b2012-06-20 16:38:30 -07001299
1300/*
1301 * FUNCTION: wlan_hdd_validate_operation_channel
1302 * called by wlan_hdd_cfg80211_start_bss() and
1303 * wlan_hdd_cfg80211_set_channel()
1304 * This function validates whether given channel is part of valid
1305 * channel list.
1306 */
1307static VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
1308{
1309
1310 v_U32_t num_ch = 0;
1311 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1312 u32 indx = 0;
1313 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301314 v_U8_t fValidChannel = FALSE, count = 0;
1315 hdd_config_t *hdd_pConfig_ini= (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07001316
1317 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1318
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301319 if ( hdd_pConfig_ini->sapAllowAllChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001320 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301321 /* Validate the channel */
1322 for (count = RF_CHAN_1 ; count <= RF_CHAN_165 ; count++)
Jeff Johnson295189b2012-06-20 16:38:30 -07001323 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301324 if ( channel == rfChannels[count].channelNum )
1325 {
1326 fValidChannel = TRUE;
1327 break;
1328 }
1329 }
1330 if (fValidChannel != TRUE)
1331 {
1332 hddLog(VOS_TRACE_LEVEL_ERROR,
1333 "%s: Invalid Channel [%d]", __func__, channel);
1334 return VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001335 }
1336 }
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301337 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001338 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301339 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1340 valid_ch, &num_ch))
1341 {
1342 hddLog(VOS_TRACE_LEVEL_ERROR,
1343 "%s: failed to get valid channel list", __func__);
1344 return VOS_STATUS_E_FAILURE;
1345 }
1346 for (indx = 0; indx < num_ch; indx++)
1347 {
1348 if (channel == valid_ch[indx])
1349 {
1350 break;
1351 }
1352 }
1353
1354 if (indx >= num_ch)
1355 {
1356 hddLog(VOS_TRACE_LEVEL_ERROR,
1357 "%s: Invalid Channel [%d]", __func__, channel);
1358 return VOS_STATUS_E_FAILURE;
1359 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001360 }
1361 return VOS_STATUS_SUCCESS;
1362
1363}
1364
Viral Modi3a32cc52013-02-08 11:14:52 -08001365/**
1366 * FUNCTION: wlan_hdd_cfg80211_set_channel
1367 * This function is used to set the channel number
1368 */
1369static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
1370 struct ieee80211_channel *chan,
1371 enum nl80211_channel_type channel_type
1372 )
1373{
1374 v_U32_t num_ch = 0;
1375 u32 channel = 0;
1376 hdd_adapter_t *pAdapter = NULL;
1377 int freq = chan->center_freq; /* freq is in MHZ */
1378
1379 ENTER();
1380
1381 if( NULL == dev )
1382 {
1383 hddLog(VOS_TRACE_LEVEL_ERROR,
1384 "%s: Called with dev = NULL.\n", __func__);
1385 return -ENODEV;
1386 }
1387 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1388
1389 hddLog(VOS_TRACE_LEVEL_INFO,
1390 "%s: device_mode = %d freq = %d \n",__func__,
1391 pAdapter->device_mode, chan->center_freq);
1392 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1393 {
1394 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1395 return -EAGAIN;
1396 }
1397
1398 /*
1399 * Do freq to chan conversion
1400 * TODO: for 11a
1401 */
1402
1403 channel = ieee80211_frequency_to_channel(freq);
1404
1405 /* Check freq range */
1406 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
1407 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
1408 {
1409 hddLog(VOS_TRACE_LEVEL_ERROR,
1410 "%s: Channel [%d] is outside valid range from %d to %d\n",
1411 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
1412 WNI_CFG_CURRENT_CHANNEL_STAMAX);
1413 return -EINVAL;
1414 }
1415
1416 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1417
1418 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode)
1419#ifdef WLAN_FEATURE_P2P
1420 && (WLAN_HDD_P2P_GO != pAdapter->device_mode)
1421#endif
1422 )
1423 {
1424 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
1425 {
1426 hddLog(VOS_TRACE_LEVEL_ERROR,
1427 "%s: Invalid Channel [%d] \n", __func__, channel);
1428 return -EINVAL;
1429 }
1430 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1431 "%s: set channel to [%d] for device mode =%d",
1432 __func__, channel,pAdapter->device_mode);
1433 }
1434 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
1435#ifdef WLAN_FEATURE_P2P
1436 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
1437#endif
1438 )
1439 {
1440 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
1441 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
1442 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1443
1444 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
1445 {
1446 /* Link is up then return cant set channel*/
1447 hddLog( VOS_TRACE_LEVEL_ERROR,
1448 "%s: IBSS Associated, can't set the channel\n", __func__);
1449 return -EINVAL;
1450 }
1451
1452 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
1453 pHddStaCtx->conn_info.operationChannel = channel;
1454 pRoamProfile->ChannelInfo.ChannelList =
1455 &pHddStaCtx->conn_info.operationChannel;
1456 }
1457 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1458#ifdef WLAN_FEATURE_P2P
1459 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1460#endif
1461 )
1462 {
1463 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1464
1465 if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
1466 {
1467 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
1468
1469 /* If auto channel selection is configured as enable/ 1 then ignore
1470 channel set by supplicant
1471 */
1472 if ( cfg_param->apAutoChannelSelection )
1473 {
1474 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = AUTO_CHANNEL_SELECT;
1475
1476 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1477 "%s: set channel to auto channel (0) for device mode =%d",
1478 __func__, pAdapter->device_mode);
1479 }
1480 }
1481 }
1482 else
1483 {
1484 hddLog(VOS_TRACE_LEVEL_FATAL,
1485 "%s: Invalid device mode failed to set valid channel", __func__);
1486 return -EINVAL;
1487 }
1488 EXIT();
1489 return 0;
1490}
1491
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301492/*
1493 * FUNCTION: wlan_hdd_select_cbmode
1494 * called by wlan_hdd_cfg80211_start_bss() and
1495 * This function selects the cbmode based on primary channel
1496 */
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001497VOS_STATUS wlan_sap_select_cbmode(void *pAdapter,eSapPhyMode SapHw_mode, v_U8_t channel)
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301498{
1499 tSmeConfigParams smeConfig;
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001500 hdd_context_t *pHddCtx = ( hdd_context_t *) pAdapter;
1501 hdd_config_t *pConfigIni = ((hdd_context_t *)(pAdapter))->cfg_ini;
1502
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301503 if(
1504#ifdef WLAN_FEATURE_11AC
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001505 SapHw_mode != eSAP_DOT11_MODE_11ac &&
1506 SapHw_mode != eSAP_DOT11_MODE_11ac_ONLY &&
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301507#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001508 SapHw_mode != eSAP_DOT11_MODE_11n &&
1509 SapHw_mode != eSAP_DOT11_MODE_11n_ONLY
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301510 )
1511 {
1512 return VOS_STATUS_SUCCESS;
1513 }
1514
1515 if (!pConfigIni->nChannelBondingMode5GHz) {
1516 return VOS_STATUS_SUCCESS;
1517 }
1518
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001519 //channel = pSapConfig->channel;
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301520 vos_mem_zero(&smeConfig, sizeof (tSmeConfigParams));
1521
1522 sme_GetConfigParam(pHddCtx->hHal, &smeConfig);
1523
1524#ifdef WLAN_FEATURE_11AC
1525
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001526 if ( SapHw_mode == eSAP_DOT11_MODE_11ac ||
1527 SapHw_mode == eSAP_DOT11_MODE_11ac_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301528 {
1529 if ( channel== 36 || channel == 52 || channel == 100 ||
1530 channel == 116 || channel == 149 )
1531 {
1532 smeConfig.csrConfig.channelBondingMode5GHz =
1533 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW - 1;
1534 }
1535 else if ( channel == 40 || channel == 56 || channel == 104 ||
1536 channel == 120 || channel == 153 )
1537 {
1538 smeConfig.csrConfig.channelBondingMode5GHz =
1539 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW - 1;
1540 }
1541 else if ( channel == 44 || channel == 60 || channel == 108 ||
1542 channel == 124 || channel == 157 )
1543 {
1544 smeConfig.csrConfig.channelBondingMode5GHz =
1545 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH -1;
1546 }
1547 else if ( channel == 48 || channel == 64 || channel == 112 ||
1548 channel == 128 || channel == 161 )
1549 {
1550 smeConfig.csrConfig.channelBondingMode5GHz =
1551 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH - 1;
1552 }
Shailender Karmuchi84f11f02013-02-12 17:11:45 -08001553 else if ( channel == 165 )
1554 {
1555 smeConfig.csrConfig.channelBondingMode5GHz = 0;
1556 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301557 }
1558#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001559 if ( SapHw_mode == eSAP_DOT11_MODE_11n ||
1560 SapHw_mode == eSAP_DOT11_MODE_11n_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301561 {
1562 if ( channel== 40 || channel == 48 || channel == 56 ||
1563 channel == 64 || channel == 104 || channel == 112 ||
1564 channel == 120 || channel == 128 || channel == 136 ||
1565 channel == 144 || channel == 153 || channel == 161 )
1566 {
1567 smeConfig.csrConfig.channelBondingMode5GHz = 1;
1568 }
1569 else if ( channel== 36 || channel == 44 || channel == 52 ||
1570 channel == 60 || channel == 100 || channel == 108 ||
1571 channel == 116 || channel == 124 || channel == 132 ||
1572 channel == 140 || channel == 149 || channel == 157 )
1573 {
1574 smeConfig.csrConfig.channelBondingMode5GHz = 2;
1575 }
Shailender Karmuchi84f11f02013-02-12 17:11:45 -08001576 else if ( channel == 165 )
1577 {
1578 smeConfig.csrConfig.channelBondingMode5GHz = 0;
1579 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301580 }
1581 pr_info ("cbmode selected=%ld\n",smeConfig.csrConfig.channelBondingMode5GHz);
1582
1583 sme_UpdateConfig (pHddCtx->hHal,&smeConfig);
1584 return VOS_STATUS_SUCCESS;
1585}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001586
Jeff Johnson295189b2012-06-20 16:38:30 -07001587#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1588static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1589 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001590#else
1591static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1592 struct cfg80211_beacon_data *params,
1593 const u8 *ssid, size_t ssid_len,
1594 enum nl80211_hidden_ssid hidden_ssid)
1595#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001596{
1597 tsap_Config_t *pConfig;
1598 beacon_data_t *pBeacon = NULL;
1599 struct ieee80211_mgmt *pMgmt_frame;
1600 v_U8_t *pIe=NULL;
1601 v_U16_t capab_info;
1602 eCsrAuthType RSNAuthType;
1603 eCsrEncryptionType RSNEncryptType;
1604 eCsrEncryptionType mcRSNEncryptType;
1605 int status = VOS_STATUS_SUCCESS;
1606 tpWLAN_SAPEventCB pSapEventCallback;
1607 hdd_hostapd_state_t *pHostapdState;
1608 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1609 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301610 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001611 struct qc_mac_acl_entry *acl_entry = NULL;
1612 v_SINT_t i;
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001613 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001614
1615 ENTER();
1616
1617 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1618
1619 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1620
1621 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1622
1623 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1624
1625 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1626
1627 //channel is already set in the set_channel Call back
1628 //pConfig->channel = pCommitConfig->channel;
1629
1630 /*Protection parameter to enable or disable*/
1631 pConfig->protEnabled =
1632 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1633
1634 pConfig->dtim_period = pBeacon->dtim_period;
1635
1636 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1637 pConfig->dtim_period);
1638
1639
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001640 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001641 {
1642 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001643 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001644 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001645 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001646 tANI_BOOLEAN restartNeeded;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001647 pConfig->ieee80211d = 1;
1648 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1649 sme_setRegInfo(hHal, pConfig->countryCode);
1650 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
Jeff Johnson295189b2012-06-20 16:38:30 -07001651 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001652 else
1653 {
1654 pConfig->ieee80211d = 0;
1655 }
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301656 /*
1657 * If auto channel is configured i.e. channel is 0,
1658 * so skip channel validation.
1659 */
1660 if( AUTO_CHANNEL_SELECT != pConfig->channel )
1661 {
1662 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1663 {
1664 hddLog(VOS_TRACE_LEVEL_ERROR,
1665 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1666 return -EINVAL;
1667 }
1668 }
1669 else
1670 {
1671 if(1 != pHddCtx->is_dynamic_channel_range_set)
1672 {
1673 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
1674 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
1675 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
1676 }
1677 pHddCtx->is_dynamic_channel_range_set = 0;
1678 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001679 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001680 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001681 {
1682 pConfig->ieee80211d = 0;
1683 }
1684 pConfig->authType = eSAP_AUTO_SWITCH;
1685
1686 capab_info = pMgmt_frame->u.beacon.capab_info;
1687
1688 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
1689 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1690
1691 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1692
1693 /*Set wps station to configured*/
1694 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1695
1696 if(pIe)
1697 {
1698 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1699 {
1700 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1701 return -EINVAL;
1702 }
1703 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1704 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001705 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001706 /* Check 15 bit of WPS IE as it contain information for wps state
1707 * WPS state
1708 */
1709 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1710 {
1711 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1712 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1713 {
1714 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1715 }
1716 }
1717 }
1718 else
1719 {
1720 pConfig->wps_state = SAP_WPS_DISABLED;
1721 }
1722 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
1723
1724 pConfig->RSNWPAReqIELength = 0;
1725 pConfig->pRSNWPAReqIE = NULL;
1726 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1727 WLAN_EID_RSN);
1728 if(pIe && pIe[1])
1729 {
1730 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1731 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1732 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1733 /* The actual processing may eventually be more extensive than
1734 * this. Right now, just consume any PMKIDs that are sent in
1735 * by the app.
1736 * */
1737 status = hdd_softap_unpackIE(
1738 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1739 &RSNEncryptType,
1740 &mcRSNEncryptType,
1741 &RSNAuthType,
1742 pConfig->pRSNWPAReqIE[1]+2,
1743 pConfig->pRSNWPAReqIE );
1744
1745 if( VOS_STATUS_SUCCESS == status )
1746 {
1747 /* Now copy over all the security attributes you have
1748 * parsed out
1749 * */
1750 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1751 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1752 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1753 = RSNEncryptType;
1754 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1755 "EncryptionType = %d mcEncryptionType = %d\n"),
1756 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1757 }
1758 }
1759
1760 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1761 pBeacon->tail, pBeacon->tail_len);
1762
1763 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1764 {
1765 if (pConfig->pRSNWPAReqIE)
1766 {
1767 /*Mixed mode WPA/WPA2*/
1768 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1769 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1770 }
1771 else
1772 {
1773 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1774 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1775 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1776 status = hdd_softap_unpackIE(
1777 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1778 &RSNEncryptType,
1779 &mcRSNEncryptType,
1780 &RSNAuthType,
1781 pConfig->pRSNWPAReqIE[1]+2,
1782 pConfig->pRSNWPAReqIE );
1783
1784 if( VOS_STATUS_SUCCESS == status )
1785 {
1786 /* Now copy over all the security attributes you have
1787 * parsed out
1788 * */
1789 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1790 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1791 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1792 = RSNEncryptType;
1793 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1794 "EncryptionType = %d mcEncryptionType = %d\n"),
1795 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1796 }
1797 }
1798 }
1799
1800 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1801
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001802#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001803 if (params->ssid != NULL)
1804 {
1805 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1806 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1807 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1808 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1809 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001810#else
1811 if (ssid != NULL)
1812 {
1813 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1814 pConfig->SSIDinfo.ssid.length = ssid_len;
1815 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1816 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1817 }
1818#endif
1819
Jeff Johnson295189b2012-06-20 16:38:30 -07001820 vos_mem_copy(pConfig->self_macaddr.bytes,
1821 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1822
1823 /* default value */
1824 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1825 pConfig->num_accept_mac = 0;
1826 pConfig->num_deny_mac = 0;
1827
1828 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1829 pBeacon->tail, pBeacon->tail_len);
1830
1831 /* pIe for black list is following form:
1832 type : 1 byte
1833 length : 1 byte
1834 OUI : 4 bytes
1835 acl type : 1 byte
1836 no of mac addr in black list: 1 byte
1837 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1838 */
1839 if ((pIe != NULL) && (pIe[1] != 0))
1840 {
1841 pConfig->SapMacaddr_acl = pIe[6];
1842 pConfig->num_deny_mac = pIe[7];
1843 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1844 pIe[6], pIe[7]);
1845 if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
1846 pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
1847 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1848 for (i = 0; i < pConfig->num_deny_mac; i++)
1849 {
1850 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1851 acl_entry++;
1852 }
1853 }
1854 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1855 pBeacon->tail, pBeacon->tail_len);
1856
1857 /* pIe for white list is following form:
1858 type : 1 byte
1859 length : 1 byte
1860 OUI : 4 bytes
1861 acl type : 1 byte
1862 no of mac addr in white list: 1 byte
1863 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1864 */
1865 if ((pIe != NULL) && (pIe[1] != 0))
1866 {
1867 pConfig->SapMacaddr_acl = pIe[6];
1868 pConfig->num_accept_mac = pIe[7];
1869 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
1870 pIe[6], pIe[7]);
1871 if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
1872 pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
1873 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1874 for (i = 0; i < pConfig->num_accept_mac; i++)
1875 {
1876 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1877 acl_entry++;
1878 }
1879 }
1880 wlan_hdd_set_sapHwmode(pHostapdAdapter);
1881
Jeff Johnsone7245742012-09-05 17:12:55 -07001882#ifdef WLAN_FEATURE_11AC
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08001883 /* Overwrite the hostapd setting for HW mode only for 11ac.
1884 * This is valid only if mode is set to 11n in hostapd and either AUTO or 11ac in .ini .
1885 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode) */
1886 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
1887 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
1888 (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
1889 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1890 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07001891 {
1892 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
1893 }
1894#endif
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301895
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001896 if( AUTO_CHANNEL_SELECT != pConfig->channel)
1897 wlan_sap_select_cbmode((WLAN_HDD_GET_CTX(pHostapdAdapter)),pConfig->SapHw_mode,pConfig->channel);
Jeff Johnson295189b2012-06-20 16:38:30 -07001898 // ht_capab is not what the name conveys,this is used for protection bitmap
1899 pConfig->ht_capab =
1900 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
1901
1902 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
1903 {
1904 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
1905 return -EINVAL;
1906 }
1907
1908 //Uapsd Enabled Bit
1909 pConfig->UapsdEnable =
1910 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
1911 //Enable OBSS protection
1912 pConfig->obssProtEnabled =
1913 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
1914
1915 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
1916 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
1917 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
1918 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
1919 (int)pConfig->channel);
1920 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
1921 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
1922 pConfig->authType);
1923 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
1924 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
1925 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
1926 pConfig->protEnabled, pConfig->obssProtEnabled);
1927
1928 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
1929 {
1930 //Bss already started. just return.
1931 //TODO Probably it should update some beacon params.
1932 hddLog( LOGE, "Bss Already started...Ignore the request");
1933 EXIT();
1934 return 0;
1935 }
1936
1937 pConfig->persona = pHostapdAdapter->device_mode;
1938
1939 pSapEventCallback = hdd_hostapd_SAPEventCB;
1940 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
1941 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
1942 {
1943 hddLog(LOGE,FL("SAP Start Bss fail\n"));
1944 return -EINVAL;
1945 }
1946
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001947 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07001948 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
1949
1950 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1951
1952 if (!VOS_IS_STATUS_SUCCESS(status))
1953 {
1954 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1955 ("ERROR: HDD vos wait for single_event failed!!\n"));
1956 VOS_ASSERT(0);
1957 }
1958
1959 //Succesfully started Bss update the state bit.
1960 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
1961
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001962#ifdef WLAN_FEATURE_P2P_DEBUG
1963 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
1964 {
1965 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
1966 {
1967 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1968 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001969 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001970 }
1971 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
1972 {
1973 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1974 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001975 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001976 }
1977 }
1978#endif
1979
Jeff Johnson295189b2012-06-20 16:38:30 -07001980 pHostapdState->bCommit = TRUE;
1981 EXIT();
1982
1983 return 0;
1984}
1985
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001986#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001987static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
1988 struct net_device *dev,
1989 struct beacon_parameters *params)
1990{
1991 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1992 int status=VOS_STATUS_SUCCESS;
1993
1994 ENTER();
1995
1996 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
1997
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001998 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1999 {
2000 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2001 "%s:LOGP in Progress. Ignore!!!", __func__);
2002 return -EAGAIN;
2003 }
2004
Jeff Johnson295189b2012-06-20 16:38:30 -07002005 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
2006#ifdef WLAN_FEATURE_P2P
2007 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2008#endif
2009 )
2010 {
2011 beacon_data_t *old,*new;
2012
2013 old = pAdapter->sessionCtx.ap.beacon;
2014
2015 if (old)
2016 return -EALREADY;
2017
2018 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2019
2020 if(status != VOS_STATUS_SUCCESS)
2021 {
2022 hddLog(VOS_TRACE_LEVEL_FATAL,
2023 "%s:Error!!! Allocating the new beacon\n",__func__);
2024 return -EINVAL;
2025 }
2026
2027 pAdapter->sessionCtx.ap.beacon = new;
2028
2029 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2030 }
2031
2032 EXIT();
2033 return status;
2034}
2035
2036static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
2037 struct net_device *dev,
2038 struct beacon_parameters *params)
2039{
2040 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2041 int status=VOS_STATUS_SUCCESS;
2042
2043 ENTER();
2044
2045 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2046 __func__,pAdapter->device_mode);
2047
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002048 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2049 {
2050 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2051 "%s:LOGP in Progress. Ignore!!!", __func__);
2052 return -EAGAIN;
2053 }
2054
Jeff Johnson295189b2012-06-20 16:38:30 -07002055 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2056#ifdef WLAN_FEATURE_P2P
2057 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2058#endif
2059 )
2060 {
2061 beacon_data_t *old,*new;
2062
2063 old = pAdapter->sessionCtx.ap.beacon;
2064
2065 if (!old)
2066 return -ENOENT;
2067
2068 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2069
2070 if(status != VOS_STATUS_SUCCESS) {
2071 hddLog(VOS_TRACE_LEVEL_FATAL,
2072 "%s: Error!!! Allocating the new beacon\n",__func__);
2073 return -EINVAL;
2074 }
2075
2076 pAdapter->sessionCtx.ap.beacon = new;
2077
2078 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2079 }
2080
2081 EXIT();
2082 return status;
2083}
2084
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002085#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
2086
2087#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002088static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
2089 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002090#else
2091static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
2092 struct net_device *dev)
2093#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002094{
2095 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07002096 hdd_context_t *pHddCtx = NULL;
2097 hdd_scaninfo_t *pScanInfo = NULL;
2098 hdd_adapter_t *staAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002099 VOS_STATUS status = 0;
2100
2101 ENTER();
2102
2103 if (NULL == pAdapter)
2104 {
2105 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002106 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002107 return -ENODEV;
2108 }
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002109 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2110 {
2111 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2112 "%s:LOGP in Progress. Ignore!!!", __func__);
2113 return -EAGAIN;
2114 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002115
2116 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2117 if (NULL == pHddCtx)
2118 {
2119 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002120 "%s: HDD context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002121 return -ENODEV;
2122 }
2123
2124 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
2125 if (NULL == staAdapter)
2126 {
2127 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
2128 if (NULL == staAdapter)
2129 {
2130 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002131 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002132 return -ENODEV;
2133 }
2134 }
2135
2136 pScanInfo = &pHddCtx->scan_info;
2137
Jeff Johnson295189b2012-06-20 16:38:30 -07002138 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2139 {
2140 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2141 return -EAGAIN;
2142 }
2143
2144 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2145
2146 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2147 __func__,pAdapter->device_mode);
2148
Jeff Johnsone7245742012-09-05 17:12:55 -07002149 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
2150 {
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002151 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Jeff Johnsone7245742012-09-05 17:12:55 -07002152 hdd_abort_mac_scan(staAdapter->pHddCtx);
2153 status = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002154 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07002155 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
2156 if (!status)
2157 {
2158 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson902c9832012-12-10 14:28:09 -08002159 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002160 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07002161 VOS_ASSERT(pScanInfo->mScanPending);
2162 return 0;
2163 }
2164 }
2165
Jeff Johnson295189b2012-06-20 16:38:30 -07002166 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2167#ifdef WLAN_FEATURE_P2P
2168 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2169#endif
2170 )
2171 {
2172 beacon_data_t *old;
2173
2174 old = pAdapter->sessionCtx.ap.beacon;
2175
2176 if (!old)
2177 return -ENOENT;
2178
2179#ifdef CONFIG_CFG80211
2180 hdd_cleanup_actionframe(pHddCtx, pAdapter);
2181#endif
2182
2183 mutex_lock(&pHddCtx->sap_lock);
2184 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2185 {
2186 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss((WLAN_HDD_GET_CTX(pAdapter))->pvosContext) ) )
2187 {
2188 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2189
2190 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2191
2192 if (!VOS_IS_STATUS_SUCCESS(status))
2193 {
2194 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2195 ("ERROR: HDD vos wait for single_event failed!!\n"));
2196 VOS_ASSERT(0);
2197 }
2198 }
2199 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2200 }
2201 mutex_unlock(&pHddCtx->sap_lock);
2202
2203 if(status != VOS_STATUS_SUCCESS)
2204 {
2205 hddLog(VOS_TRACE_LEVEL_FATAL,
2206 "%s:Error!!! Stopping the BSS\n",__func__);
2207 return -EINVAL;
2208 }
2209
2210 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2211 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
2212 ==eHAL_STATUS_FAILURE)
2213 {
2214 hddLog(LOGE,
2215 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
2216 }
2217
2218 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2219 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2220 eANI_BOOLEAN_FALSE) )
2221 {
2222 hddLog(LOGE,
2223 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
2224 }
2225
2226 // Reset WNI_CFG_PROBE_RSP Flags
2227 wlan_hdd_reset_prob_rspies(pAdapter);
2228
2229 pAdapter->sessionCtx.ap.beacon = NULL;
2230 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002231#ifdef WLAN_FEATURE_P2P_DEBUG
2232 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
2233 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
2234 {
2235 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
2236 "GO got removed");
2237 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
2238 }
2239#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002240 }
2241 EXIT();
2242 return status;
2243}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002244
2245#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2246
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302247static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2248 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002249 struct cfg80211_ap_settings *params)
2250{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302251 hdd_adapter_t *pAdapter;
2252 hdd_context_t *pHddCtx;
2253 int status = 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002254
2255 ENTER();
2256
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302257 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002258 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302259 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2260 "%s: Device is Null", __func__);
2261 return -ENODEV;
2262 }
2263
2264 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2265 if (NULL == pAdapter)
2266 {
2267 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2268 "%s: HDD adapter is Null", __func__);
2269 return -ENODEV;
2270 }
2271
2272 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2273 {
2274 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2275 "%s: HDD adapter magic is invalid", __func__);
2276 return -ENODEV;
2277 }
2278
2279 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2280 if (NULL == pHddCtx)
2281 {
2282 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2283 "%s: HDD context is Null", __func__);
2284 return -ENODEV;
2285 }
2286
2287 if (pHddCtx->isLogpInProgress)
2288 {
2289 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2290 "%s: LOGP in Progress. Ignore!!!", __func__);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002291 return -EAGAIN;
2292 }
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302293
2294 if (pHddCtx->isLoadUnloadInProgress)
2295 {
2296 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2297 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
2298 return -EAGAIN;
2299 }
2300
2301 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2302 __func__, pAdapter->device_mode);
2303
2304 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002305#ifdef WLAN_FEATURE_P2P
2306 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2307#endif
2308 )
2309 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302310 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002311
2312 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302313
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002314 if (old)
2315 return -EALREADY;
2316
2317 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2318
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302319 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002320 {
2321 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302322 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002323 return -EINVAL;
2324 }
2325 pAdapter->sessionCtx.ap.beacon = new;
Viral Modi3a32cc52013-02-08 11:14:52 -08002326#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2327 wlan_hdd_cfg80211_set_channel(wiphy, dev, params->channel, params->channel_type);
2328#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002329 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2330 params->ssid_len, params->hidden_ssid);
2331 }
2332
2333 EXIT();
2334 return status;
2335}
2336
2337
2338static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
2339 struct net_device *dev,
2340 struct cfg80211_beacon_data *params)
2341{
2342 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2343 int status=VOS_STATUS_SUCCESS;
2344
2345 ENTER();
2346
2347 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2348 __func__, pAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002349 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2350 {
2351 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2352 return -EAGAIN;
2353 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002354
2355 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2356#ifdef WLAN_FEATURE_P2P
2357 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2358#endif
2359 )
2360 {
2361 beacon_data_t *old,*new;
2362
2363 old = pAdapter->sessionCtx.ap.beacon;
2364
2365 if (!old)
2366 return -ENOENT;
2367
2368 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2369
2370 if(status != VOS_STATUS_SUCCESS) {
2371 hddLog(VOS_TRACE_LEVEL_FATAL,
2372 "%s: Error!!! Allocating the new beacon\n",__func__);
2373 return -EINVAL;
2374 }
2375
2376 pAdapter->sessionCtx.ap.beacon = new;
2377
2378 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2379 }
2380
2381 EXIT();
2382 return status;
2383}
2384
2385#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2386
Jeff Johnson295189b2012-06-20 16:38:30 -07002387
2388static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2389 struct net_device *dev,
2390 struct bss_parameters *params)
2391{
2392 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2393
2394 ENTER();
2395
2396 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2397 __func__,pAdapter->device_mode);
2398
2399 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2400#ifdef WLAN_FEATURE_P2P
2401 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2402#endif
2403 )
2404 {
2405 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2406 * want to update this parameter */
2407 if (-1 != params->ap_isolate)
2408 {
2409 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
2410 }
2411 }
2412
2413 EXIT();
2414 return 0;
2415}
2416
2417/*
2418 * FUNCTION: wlan_hdd_cfg80211_change_iface
2419 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2420 */
2421int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2422 struct net_device *ndev,
2423 enum nl80211_iftype type,
2424 u32 *flags,
2425 struct vif_params *params
2426 )
2427{
2428 struct wireless_dev *wdev;
2429 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2430 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002431 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002432 tCsrRoamProfile *pRoamProfile = NULL;
2433 eCsrRoamBssType LastBSSType;
2434 hdd_config_t *pConfig = pHddCtx->cfg_ini;
2435 eMib_dot11DesiredBssType connectedBssType;
2436 VOS_STATUS status;
2437
2438 ENTER();
2439
2440 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2441 {
2442 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2443 return -EAGAIN;
2444 }
2445
2446 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2447 __func__, pAdapter->device_mode);
2448
2449 wdev = ndev->ieee80211_ptr;
2450
2451#ifdef WLAN_BTAMP_FEATURE
2452 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2453 (NL80211_IFTYPE_ADHOC == type)||
2454 (NL80211_IFTYPE_AP == type)||
2455 (NL80211_IFTYPE_P2P_GO == type))
2456 {
2457 pHddCtx->isAmpAllowed = VOS_FALSE;
2458 // stop AMP traffic
2459 status = WLANBAP_StopAmp();
2460 if(VOS_STATUS_SUCCESS != status )
2461 {
2462 pHddCtx->isAmpAllowed = VOS_TRUE;
2463 hddLog(VOS_TRACE_LEVEL_FATAL,
2464 "%s: Failed to stop AMP", __func__);
2465 return -EINVAL;
2466 }
2467 }
2468#endif //WLAN_BTAMP_FEATURE
2469 /* Reset the current device mode bit mask*/
2470 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2471
2472 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2473#ifdef WLAN_FEATURE_P2P
2474 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002475 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002476#endif
2477 )
2478 {
2479 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2480 pRoamProfile = &pWextState->roamProfile;
2481 LastBSSType = pRoamProfile->BSSType;
2482
2483 switch (type)
2484 {
2485 case NL80211_IFTYPE_STATION:
2486#ifdef WLAN_FEATURE_P2P
2487 case NL80211_IFTYPE_P2P_CLIENT:
2488#endif
2489 hddLog(VOS_TRACE_LEVEL_INFO,
2490 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2491 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002492#ifdef WLAN_FEATURE_11AC
2493 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2494 {
2495 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2496 }
2497#endif
2498 pRoamProfile->phyMode =
2499 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002500 wdev->iftype = type;
2501#ifdef WLAN_FEATURE_P2P
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002502 //Check for sub-string p2p to confirm its a p2p interface
2503 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002504 {
2505 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2506 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2507 }
2508 else
2509 {
2510 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002511 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002512 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002513#endif
2514 break;
2515 case NL80211_IFTYPE_ADHOC:
2516 hddLog(VOS_TRACE_LEVEL_INFO,
2517 "%s: setting interface Type to ADHOC", __func__);
2518 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2519 pRoamProfile->phyMode =
2520 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
2521 wdev->iftype = type;
2522 break;
2523
2524 case NL80211_IFTYPE_AP:
2525#ifdef WLAN_FEATURE_P2P
2526 case NL80211_IFTYPE_P2P_GO:
2527#endif
2528 {
2529 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2530 "%s: setting interface Type to %s", __func__,
2531 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2532
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002533 //Cancel any remain on channel for GO mode
2534 if (NL80211_IFTYPE_P2P_GO == type)
2535 {
2536 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2537 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002538 if (NL80211_IFTYPE_AP == type)
2539 {
2540 /* As Loading WLAN Driver one interface being created for p2p device
2541 * address. This will take one HW STA and the max number of clients
2542 * that can connect to softAP will be reduced by one. so while changing
2543 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2544 * interface as it is not required in SoftAP mode.
2545 */
2546
2547 // Get P2P Adapter
2548 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2549
2550 if (pP2pAdapter)
2551 {
2552 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2553 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2554 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2555 }
2556 }
2557
Jeff Johnson295189b2012-06-20 16:38:30 -07002558 //De-init the adapter.
2559 hdd_stop_adapter( pHddCtx, pAdapter );
2560 hdd_deinit_adapter( pHddCtx, pAdapter );
2561 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2562#ifdef WLAN_SOFTAP_FEATURE
2563#ifdef WLAN_FEATURE_P2P
2564 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2565 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2566#else
2567 pAdapter->device_mode = WLAN_HDD_SOFTAP;
2568#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07002569
2570 //Disable BMPS and IMPS if enabled
2571 //before starting Go
2572 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2573 {
2574 if(VOS_STATUS_E_FAILURE ==
2575 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2576 {
2577 //Fail to Exit BMPS
2578 VOS_ASSERT(0);
2579 }
2580 }
2581
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002582 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2583 (pConfig->apRandomBssidEnabled))
2584 {
2585 /* To meet Android requirements create a randomized
2586 MAC address of the form 02:1A:11:Fx:xx:xx */
2587 get_random_bytes(&ndev->dev_addr[3], 3);
2588 ndev->dev_addr[0] = 0x02;
2589 ndev->dev_addr[1] = 0x1A;
2590 ndev->dev_addr[2] = 0x11;
2591 ndev->dev_addr[3] |= 0xF0;
2592 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2593 VOS_MAC_ADDR_SIZE);
2594 pr_info("wlan: Generated HotSpot BSSID "
2595 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2596 ndev->dev_addr[0],
2597 ndev->dev_addr[1],
2598 ndev->dev_addr[2],
2599 ndev->dev_addr[3],
2600 ndev->dev_addr[4],
2601 ndev->dev_addr[5]);
2602 }
2603
Jeff Johnson295189b2012-06-20 16:38:30 -07002604 hdd_set_ap_ops( pAdapter->dev );
2605
2606 status = hdd_init_ap_mode(pAdapter);
2607 if(status != VOS_STATUS_SUCCESS)
2608 {
2609 hddLog(VOS_TRACE_LEVEL_FATAL,
2610 "%s: Error initializing the ap mode", __func__);
2611 return -EINVAL;
2612 }
2613 hdd_set_conparam(1);
2614
2615#endif
2616 /*interface type changed update in wiphy structure*/
2617 if(wdev)
2618 {
2619 wdev->iftype = type;
2620 pHddCtx->change_iface = type;
2621 }
2622 else
2623 {
2624 hddLog(VOS_TRACE_LEVEL_ERROR,
2625 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2626 return -EINVAL;
2627 }
2628 goto done;
2629 }
2630
2631 default:
2632 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2633 __func__);
2634 return -EOPNOTSUPP;
2635 }
2636 }
2637 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
2638#ifdef WLAN_FEATURE_P2P
2639 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2640#endif
2641 )
2642 {
2643 switch(type)
2644 {
2645 case NL80211_IFTYPE_STATION:
2646#ifdef WLAN_FEATURE_P2P
2647 case NL80211_IFTYPE_P2P_CLIENT:
2648#endif
2649 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002650 hdd_stop_adapter( pHddCtx, pAdapter );
2651 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002652 wdev->iftype = type;
2653#ifdef WLAN_FEATURE_P2P
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002654 //Check for sub-string p2p to confirm its a p2p interface
2655 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002656 {
2657 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2658 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2659 }
2660 else
2661 {
2662 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002663 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002664 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002665#endif
2666 hdd_set_conparam(0);
2667 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002668 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2669 hdd_set_station_ops( pAdapter->dev );
2670 status = hdd_init_station_mode( pAdapter );
2671 if( VOS_STATUS_SUCCESS != status )
2672 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002673 /* In case of JB, for P2P-GO, only change interface will be called,
2674 * This is the right place to enable back bmps_imps()
2675 */
2676 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002677 goto done;
2678 case NL80211_IFTYPE_AP:
2679#ifdef WLAN_FEATURE_P2P
2680 case NL80211_IFTYPE_P2P_GO:
2681#endif
2682 wdev->iftype = type;
2683#ifdef WLAN_FEATURE_P2P
2684 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2685 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2686#endif
2687 goto done;
2688 default:
2689 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2690 __func__);
2691 return -EOPNOTSUPP;
2692
2693 }
2694
2695 }
2696 else
2697 {
2698 return -EOPNOTSUPP;
2699 }
2700
2701
2702 if(pRoamProfile)
2703 {
2704 if ( LastBSSType != pRoamProfile->BSSType )
2705 {
2706 /*interface type changed update in wiphy structure*/
2707 wdev->iftype = type;
2708
2709 /*the BSS mode changed, We need to issue disconnect
2710 if connected or in IBSS disconnect state*/
2711 if ( hdd_connGetConnectedBssType(
2712 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2713 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2714 {
2715 /*need to issue a disconnect to CSR.*/
2716 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2717 if( eHAL_STATUS_SUCCESS ==
2718 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2719 pAdapter->sessionId,
2720 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2721 {
2722 wait_for_completion_interruptible_timeout(
2723 &pAdapter->disconnect_comp_var,
2724 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2725 }
2726 }
2727 }
2728 }
2729
2730done:
2731 /*set bitmask based on updated value*/
2732 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
2733#ifdef WLAN_BTAMP_FEATURE
2734 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
2735 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2736 {
2737 //we are ok to do AMP
2738 pHddCtx->isAmpAllowed = VOS_TRUE;
2739 }
2740#endif //WLAN_BTAMP_FEATURE
2741 EXIT();
2742 return 0;
2743}
2744
2745static int wlan_hdd_change_station(struct wiphy *wiphy,
2746 struct net_device *dev,
2747 u8 *mac,
2748 struct station_parameters *params)
2749{
2750 VOS_STATUS status = VOS_STATUS_SUCCESS;
2751 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2752 v_MACADDR_t STAMacAddress;
2753
Jeff Johnsone7245742012-09-05 17:12:55 -07002754 ENTER();
2755
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002756 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2757 {
2758 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2759 "%s:LOGP in Progress. Ignore!!!", __func__);
2760 return -EAGAIN;
2761 }
2762
Jeff Johnson295189b2012-06-20 16:38:30 -07002763 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
2764
2765 if ( ( pAdapter->device_mode == WLAN_HDD_SOFTAP )
2766#ifdef WLAN_FEATURE_P2P
2767 || ( pAdapter->device_mode == WLAN_HDD_P2P_GO )
2768#endif
2769 )
2770 {
2771 if(params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
2772 {
2773 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
2774 WLANTL_STA_AUTHENTICATED);
2775
2776 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002777 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002778 return -EINVAL;
2779 }
2780 }
2781
Jeff Johnsone7245742012-09-05 17:12:55 -07002782 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002783 return status;
2784}
2785
2786/*
2787 * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
2788 * This function is used to get peer station index in IBSS mode
2789 */
2790static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
2791{
2792 u8 idx = 0;
2793 u8 temp[VOS_MAC_ADDR_SIZE] = {0};
2794 ENTER();
2795 memset(temp, 0, VOS_MAC_ADDR_SIZE);
2796 for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
2797 {
2798 if ( (0 !=
2799 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
2800 && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
2801 temp, VOS_MAC_ADDR_SIZE)
2802 )
2803 {
2804 return idx;
2805 }
2806 }
2807 return idx;
2808}
2809
2810
2811/*
2812 * FUNCTION: wlan_hdd_cfg80211_add_key
2813 * This function is used to initialize the key information
2814 */
2815#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2816static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2817 struct net_device *ndev,
2818 u8 key_index, bool pairwise,
2819 const u8 *mac_addr,
2820 struct key_params *params
2821 )
2822#else
2823static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2824 struct net_device *ndev,
2825 u8 key_index, const u8 *mac_addr,
2826 struct key_params *params
2827 )
2828#endif
2829{
2830 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2831 tCsrRoamSetKey setKey;
2832 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
2833 int status = 0;
2834 v_U32_t roamId= 0xFF;
2835 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2836 hdd_hostapd_state_t *pHostapdState;
2837 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07002838 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07002839
2840 ENTER();
2841
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002842 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2843 {
2844 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2845 "%s:LOGP in Progress. Ignore!!!", __func__);
2846 return -EAGAIN;
2847 }
2848
Jeff Johnson295189b2012-06-20 16:38:30 -07002849 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2850 __func__,pAdapter->device_mode);
2851
2852 if (CSR_MAX_NUM_KEY <= key_index)
2853 {
2854 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
2855 key_index);
2856
2857 return -EINVAL;
2858 }
2859
2860 hddLog(VOS_TRACE_LEVEL_INFO,
2861 "%s: called with key index = %d & key length %d",
2862 __func__, key_index, params->key_len);
2863
2864 /*extract key idx, key len and key*/
2865 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2866 setKey.keyId = key_index;
2867 setKey.keyLength = params->key_len;
2868 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
2869
2870 switch (params->cipher)
2871 {
2872 case WLAN_CIPHER_SUITE_WEP40:
2873 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
2874 break;
2875
2876 case WLAN_CIPHER_SUITE_WEP104:
2877 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
2878 break;
2879
2880 case WLAN_CIPHER_SUITE_TKIP:
2881 {
2882 u8 *pKey = &setKey.Key[0];
2883 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
2884
2885 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
2886
2887 /*Supplicant sends the 32bytes key in this order
2888
2889 |--------------|----------|----------|
2890 | Tk1 |TX-MIC | RX Mic |
2891 |--------------|----------|----------|
2892 <---16bytes---><--8bytes--><--8bytes-->
2893
2894 */
2895 /*Sme expects the 32 bytes key to be in the below order
2896
2897 |--------------|----------|----------|
2898 | Tk1 |RX-MIC | TX Mic |
2899 |--------------|----------|----------|
2900 <---16bytes---><--8bytes--><--8bytes-->
2901 */
2902 /* Copy the Temporal Key 1 (TK1) */
2903 vos_mem_copy(pKey, params->key,16);
2904
2905 /*Copy the rx mic first*/
2906 vos_mem_copy(&pKey[16],&params->key[24],8);
2907
2908 /*Copy the tx mic */
2909 vos_mem_copy(&pKey[24],&params->key[16],8);
2910
2911
2912 break;
2913 }
2914
2915 case WLAN_CIPHER_SUITE_CCMP:
2916 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
2917 break;
2918
2919#ifdef FEATURE_WLAN_WAPI
2920 case WLAN_CIPHER_SUITE_SMS4:
2921 {
2922 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2923 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
2924 params->key, params->key_len);
2925 return 0;
2926 }
2927#endif
2928#ifdef FEATURE_WLAN_CCX
2929 case WLAN_CIPHER_SUITE_KRK:
2930 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
2931 break;
2932#endif
2933 default:
2934 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
2935 __func__, params->cipher);
2936 return -EOPNOTSUPP;
2937 }
2938
2939 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
2940 __func__, setKey.encType);
2941
2942
2943
2944 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2945#ifdef WLAN_FEATURE_P2P
2946 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2947#endif
2948 )
2949 {
2950
2951
2952 if (
2953#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2954 (!pairwise)
2955#else
2956 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2957#endif
2958 )
2959 {
2960 /* set group key*/
2961 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson1250df42012-12-10 14:31:52 -08002962 "%s- %d: setting Broadcast key",
Jeff Johnson295189b2012-06-20 16:38:30 -07002963 __func__, __LINE__);
2964 setKey.keyDirection = eSIR_RX_ONLY;
2965 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2966 }
2967 else
2968 {
2969 /* set pairwise key*/
2970 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2971 "%s- %d: setting pairwise key",
2972 __func__, __LINE__);
2973 setKey.keyDirection = eSIR_TX_RX;
2974 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2975 }
2976
2977 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2978 if( pHostapdState->bssState == BSS_START )
2979 {
2980 status = WLANSAP_SetKeySta( pVosContext, &setKey);
2981
2982 if ( status != eHAL_STATUS_SUCCESS )
2983 {
2984 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2985 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
2986 __LINE__, status );
2987 }
2988 }
2989
2990 /* Saving WEP keys */
2991 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
2992 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
2993 {
2994 //Save the wep key in ap context. Issue setkey after the BSS is started.
2995 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2996 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
2997 }
2998 else
2999 {
3000 //Save the key in ap context. Issue setkey after the BSS is started.
3001 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3002 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
3003 }
3004 }
3005 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3006#ifdef WLAN_FEATURE_P2P
3007 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3008#endif
3009 )
3010 {
3011 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3012 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3013
3014 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
3015
Venkata Prathyusha Kuntupalliee2ce712013-01-17 14:09:24 -08003016 pWextState->roamProfile.Keys.defaultIndex = key_index;
3017
3018
Jeff Johnson295189b2012-06-20 16:38:30 -07003019 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
3020 params->key, params->key_len);
3021
3022 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3023
3024 if (!( ( IW_AUTH_KEY_MGMT_802_1X
3025 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
3026 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3027 )
3028 &&
3029 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3030 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3031 )
3032 )
3033 {
3034 /* in case of static WEP, macaddr/bssid is not coming from nl80211
3035 * interface, copy bssid for pairwise key and group macaddr for
3036 * group key initialization*/
3037
3038 tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
3039
3040 pWextState->roamProfile.negotiatedUCEncryptionType =
3041 pHddStaCtx->conn_info.ucEncryptionType =
3042 ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
3043 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
3044 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
3045
3046
3047 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3048 "%s: Negotiated encryption type %d", __func__,
3049 pWextState->roamProfile.negotiatedUCEncryptionType);
3050
3051 sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
3052 &pWextState->roamProfile, true);
3053 setKey.keyLength = 0;
3054 setKey.keyDirection = eSIR_TX_RX;
3055
3056#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3057 if (pairwise)
3058 {
3059#endif
3060 if (mac_addr)
3061 {
3062 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3063 }
3064 else
3065 {
3066 /* macaddr is NULL, set the peerMac to bssId in case of BSS,
3067 * and peerMacAddress in case of IBSS*/
3068 if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
3069 {
3070 u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
3071 if (HDD_MAX_NUM_IBSS_STA != staidx)
3072 {
3073 vos_mem_copy(setKey.peerMac,
3074 &pHddStaCtx->conn_info.peerMacAddress[staidx],
3075 WNI_CFG_BSSID_LEN);
3076
3077 }
3078 else
3079 {
3080 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
3081 __func__);
3082 return -EOPNOTSUPP;
3083 }
3084 }
3085 else
3086 {
3087 vos_mem_copy(setKey.peerMac,
3088 &pHddStaCtx->conn_info.bssId[0],
3089 WNI_CFG_BSSID_LEN);
3090 }
3091 }
3092#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3093 }
3094 else
3095 {
3096 /* set group key*/
3097 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3098 "%s- %d: setting Group key",
3099 __func__, __LINE__);
3100 setKey.keyDirection = eSIR_RX_ONLY;
3101 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3102 }
3103#endif
3104 }
3105 else if (
3106#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3107 (!pairwise)
3108#else
3109 (!mac_addr || is_broadcast_ether_addr(mac_addr))
3110#endif
3111 )
3112 {
3113 /* set group key*/
3114 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3115 "%s- %d: setting Group key",
3116 __func__, __LINE__);
3117 setKey.keyDirection = eSIR_RX_ONLY;
3118 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3119 }
3120 else
3121 {
3122 /* set pairwise key*/
3123 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3124 "%s- %d: setting pairwise key",
3125 __func__, __LINE__);
3126 setKey.keyDirection = eSIR_TX_RX;
3127 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3128 }
3129
3130 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3131 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3132 __func__, setKey.peerMac[0], setKey.peerMac[1],
3133 setKey.peerMac[2], setKey.peerMac[3],
3134 setKey.peerMac[4], setKey.peerMac[5],
3135 setKey.keyDirection);
3136
3137 vos_status = wlan_hdd_check_ula_done(pAdapter);
3138
3139 if ( vos_status != VOS_STATUS_SUCCESS )
3140 {
3141 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3142 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
3143 __LINE__, vos_status );
3144
3145 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3146
3147 return -EINVAL;
3148
3149 }
3150
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003151#ifdef WLAN_FEATURE_VOWIFI_11R
3152 /* The supplicant may attempt to set the PTK once pre-authentication is done.
3153 Save the key in the UMAC and include it in the ADD BSS request */
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003154 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303155 if( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_WAIT )
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003156 {
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303157 return -EINVAL;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003158 }
3159#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07003160
3161 /* issue set key request to SME*/
3162 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3163 pAdapter->sessionId, &setKey, &roamId );
3164
3165 if ( 0 != status )
3166 {
3167 hddLog(VOS_TRACE_LEVEL_ERROR,
3168 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3169 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3170 return -EINVAL;
3171 }
3172
3173
3174 /* in case of IBSS as there was no information available about WEP keys during
3175 * IBSS join, group key intialized with NULL key, so re-initialize group key
3176 * with correct value*/
3177 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
3178 !( ( IW_AUTH_KEY_MGMT_802_1X
3179 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
3180 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3181 )
3182 &&
3183 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3184 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3185 )
3186 )
3187 {
3188 setKey.keyDirection = eSIR_RX_ONLY;
3189 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3190
3191 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3192 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3193 __func__, setKey.peerMac[0], setKey.peerMac[1],
3194 setKey.peerMac[2], setKey.peerMac[3],
3195 setKey.peerMac[4], setKey.peerMac[5],
3196 setKey.keyDirection);
3197
3198 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3199 pAdapter->sessionId, &setKey, &roamId );
3200
3201 if ( 0 != status )
3202 {
3203 hddLog(VOS_TRACE_LEVEL_ERROR,
3204 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
3205 __func__, status);
3206 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3207 return -EINVAL;
3208 }
3209 }
3210 }
3211
3212 return 0;
3213}
3214
3215/*
3216 * FUNCTION: wlan_hdd_cfg80211_get_key
3217 * This function is used to get the key information
3218 */
3219#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3220static int wlan_hdd_cfg80211_get_key(
3221 struct wiphy *wiphy,
3222 struct net_device *ndev,
3223 u8 key_index, bool pairwise,
3224 const u8 *mac_addr, void *cookie,
3225 void (*callback)(void *cookie, struct key_params*)
3226 )
3227#else
3228static int wlan_hdd_cfg80211_get_key(
3229 struct wiphy *wiphy,
3230 struct net_device *ndev,
3231 u8 key_index, const u8 *mac_addr, void *cookie,
3232 void (*callback)(void *cookie, struct key_params*)
3233 )
3234#endif
3235{
3236 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3237 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3238 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
3239 struct key_params params;
3240
3241 ENTER();
3242
3243 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3244 __func__,pAdapter->device_mode);
3245
3246 memset(&params, 0, sizeof(params));
3247
3248 if (CSR_MAX_NUM_KEY <= key_index)
3249 {
3250 return -EINVAL;
3251 }
3252
3253 switch(pRoamProfile->EncryptionType.encryptionType[0])
3254 {
3255 case eCSR_ENCRYPT_TYPE_NONE:
3256 params.cipher = IW_AUTH_CIPHER_NONE;
3257 break;
3258
3259 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3260 case eCSR_ENCRYPT_TYPE_WEP40:
3261 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3262 break;
3263
3264 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3265 case eCSR_ENCRYPT_TYPE_WEP104:
3266 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3267 break;
3268
3269 case eCSR_ENCRYPT_TYPE_TKIP:
3270 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3271 break;
3272
3273 case eCSR_ENCRYPT_TYPE_AES:
3274 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3275 break;
3276
3277 default:
3278 params.cipher = IW_AUTH_CIPHER_NONE;
3279 break;
3280 }
3281
3282 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3283 params.seq_len = 0;
3284 params.seq = NULL;
3285 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3286 callback(cookie, &params);
3287 return 0;
3288}
3289
3290/*
3291 * FUNCTION: wlan_hdd_cfg80211_del_key
3292 * This function is used to delete the key information
3293 */
3294#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3295static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3296 struct net_device *ndev,
3297 u8 key_index,
3298 bool pairwise,
3299 const u8 *mac_addr
3300 )
3301#else
3302static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3303 struct net_device *ndev,
3304 u8 key_index,
3305 const u8 *mac_addr
3306 )
3307#endif
3308{
3309 int status = 0;
3310
3311 //This code needs to be revisited. There is sme_removeKey API, we should
3312 //plan to use that. After the change to use correct index in setkey,
3313 //it is observed that this is invalidating peer
3314 //key index whenever re-key is done. This is affecting data link.
3315 //It should be ok to ignore del_key.
3316#if 0
3317 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3318 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
3319 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3320 tCsrRoamSetKey setKey;
3321 v_U32_t roamId= 0xFF;
3322
3323 ENTER();
3324
3325 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3326 __func__,pAdapter->device_mode);
3327
3328 if (CSR_MAX_NUM_KEY <= key_index)
3329 {
3330 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3331 key_index);
3332
3333 return -EINVAL;
3334 }
3335
3336 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3337 setKey.keyId = key_index;
3338
3339 if (mac_addr)
3340 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3341 else
3342 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3343
3344 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3345
3346 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3347#ifdef WLAN_FEATURE_P2P
3348 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
3349#endif
3350 )
3351 {
3352
3353 hdd_hostapd_state_t *pHostapdState =
3354 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3355 if( pHostapdState->bssState == BSS_START)
3356 {
3357 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3358
3359 if ( status != eHAL_STATUS_SUCCESS )
3360 {
3361 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3362 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3363 __LINE__, status );
3364 }
3365 }
3366 }
3367 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3368#ifdef WLAN_FEATURE_P2P
3369 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3370#endif
3371 )
3372 {
3373 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3374
3375 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3376
3377 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3378 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
3379 __func__, setKey.peerMac[0], setKey.peerMac[1],
3380 setKey.peerMac[2], setKey.peerMac[3],
3381 setKey.peerMac[4], setKey.peerMac[5]);
3382 if(pAdapter->sessionCtx.station.conn_info.connState ==
3383 eConnectionState_Associated)
3384 {
3385 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3386 pAdapter->sessionId, &setKey, &roamId );
3387
3388 if ( 0 != status )
3389 {
3390 hddLog(VOS_TRACE_LEVEL_ERROR,
3391 "%s: sme_RoamSetKey failure, returned %d",
3392 __func__, status);
3393 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3394 return -EINVAL;
3395 }
3396 }
3397 }
3398#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003399 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003400 return status;
3401}
3402
3403/*
3404 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3405 * This function is used to set the default tx key index
3406 */
3407#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3408static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3409 struct net_device *ndev,
3410 u8 key_index,
3411 bool unicast, bool multicast)
3412#else
3413static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3414 struct net_device *ndev,
3415 u8 key_index)
3416#endif
3417{
3418 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3419 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3420 int status = 0;
3421 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3422
3423 ENTER();
3424
3425 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3426 __func__,pAdapter->device_mode, key_index);
3427
3428 if (CSR_MAX_NUM_KEY <= key_index)
3429 {
3430 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3431 key_index);
3432
3433 return -EINVAL;
3434 }
3435
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003436 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3437 {
3438 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3439 "%s:LOGP in Progress. Ignore!!!", __func__);
3440 return -EAGAIN;
3441 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003442
3443 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3444#ifdef WLAN_FEATURE_P2P
3445 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3446#endif
3447 )
3448 {
3449 if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
3450 (eCSR_ENCRYPT_TYPE_TKIP !=
3451 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3452 (eCSR_ENCRYPT_TYPE_AES !=
3453 pWextState->roamProfile.EncryptionType.encryptionType[0])
3454 )
3455 {
3456 /* if default key index is not same as previous one,
3457 * then update the default key index */
3458
3459 tCsrRoamSetKey setKey;
3460 v_U32_t roamId= 0xFF;
3461 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
3462
3463 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
3464 __func__, key_index);
3465
3466 Keys->defaultIndex = (u8)key_index;
3467 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3468 setKey.keyId = key_index;
3469 setKey.keyLength = Keys->KeyLength[key_index];
3470
3471 vos_mem_copy(&setKey.Key[0],
3472 &Keys->KeyMaterial[key_index][0],
3473 Keys->KeyLength[key_index]);
3474
3475 setKey.keyDirection = eSIR_TX_ONLY;
3476
3477 vos_mem_copy(setKey.peerMac,
3478 &pHddStaCtx->conn_info.bssId[0],
3479 WNI_CFG_BSSID_LEN);
3480
3481 setKey.encType =
3482 pWextState->roamProfile.EncryptionType.encryptionType[0];
3483
3484 /* issue set key request */
3485 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3486 pAdapter->sessionId, &setKey, &roamId );
3487
3488 if ( 0 != status )
3489 {
3490 hddLog(VOS_TRACE_LEVEL_ERROR,
3491 "%s: sme_RoamSetKey failed, returned %d", __func__,
3492 status);
3493 return -EINVAL;
3494 }
3495 }
3496 }
3497
3498 /* In SoftAp mode setting key direction for default mode */
3499 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3500 {
3501 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3502 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3503 (eCSR_ENCRYPT_TYPE_AES !=
3504 pWextState->roamProfile.EncryptionType.encryptionType[0])
3505 )
3506 {
3507 /* Saving key direction for default key index to TX default */
3508 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3509 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3510 }
3511 }
3512
3513 return status;
3514}
3515
Jeff Johnson295189b2012-06-20 16:38:30 -07003516/*
3517 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3518 * This function is used to inform the BSS details to nl80211 interface.
3519 */
3520static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3521 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3522{
3523 struct net_device *dev = pAdapter->dev;
3524 struct wireless_dev *wdev = dev->ieee80211_ptr;
3525 struct wiphy *wiphy = wdev->wiphy;
3526 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3527 int chan_no;
3528 int ie_length;
3529 const char *ie;
3530 unsigned int freq;
3531 struct ieee80211_channel *chan;
3532 int rssi = 0;
3533 struct cfg80211_bss *bss = NULL;
3534
3535 ENTER();
3536
3537 if( NULL == pBssDesc )
3538 {
3539 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3540 return bss;
3541 }
3542
3543 chan_no = pBssDesc->channelId;
3544 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3545 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3546
3547 if( NULL == ie )
3548 {
3549 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3550 return bss;
3551 }
3552
3553#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3554 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3555 {
3556 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3557 }
3558 else
3559 {
3560 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3561 }
3562#else
3563 freq = ieee80211_channel_to_frequency(chan_no);
3564#endif
3565
3566 chan = __ieee80211_get_channel(wiphy, freq);
3567
3568 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3569 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3570 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3571 if (bss == NULL)
3572 {
3573 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3574
3575 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3576 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3577 pBssDesc->capabilityInfo,
3578 pBssDesc->beaconInterval, ie, ie_length,
3579 rssi, GFP_KERNEL ));
3580}
3581 else
3582 {
3583 return bss;
3584 }
3585}
3586
3587
3588
3589/*
3590 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3591 * This function is used to inform the BSS details to nl80211 interface.
3592 */
3593struct cfg80211_bss*
3594wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3595 tSirBssDescription *bss_desc
3596 )
3597{
3598 /*
3599 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3600 already exists in bss data base of cfg80211 for that particular BSS ID.
3601 Using cfg80211_inform_bss_frame to update the bss entry instead of
3602 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3603 now there is no possibility to get the mgmt(probe response) frame from PE,
3604 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3605 cfg80211_inform_bss_frame.
3606 */
3607 struct net_device *dev = pAdapter->dev;
3608 struct wireless_dev *wdev = dev->ieee80211_ptr;
3609 struct wiphy *wiphy = wdev->wiphy;
3610 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003611#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3612 qcom_ie_age *qie_age = NULL;
3613 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3614#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003615 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003616#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003617 const char *ie =
3618 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3619 unsigned int freq;
3620 struct ieee80211_channel *chan;
3621 struct ieee80211_mgmt *mgmt =
3622 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3623 struct cfg80211_bss *bss_status = NULL;
3624 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3625 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003626#ifdef WLAN_OPEN_SOURCE
3627 struct timespec ts;
3628#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003629
3630 ENTER();
3631
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003632 if (!mgmt)
3633 return NULL;
3634
Jeff Johnson295189b2012-06-20 16:38:30 -07003635 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003636
3637#ifdef WLAN_OPEN_SOURCE
3638 /* Android does not want the timestamp from the frame.
3639 Instead it wants a monotonic increasing value */
3640 get_monotonic_boottime(&ts);
3641 mgmt->u.probe_resp.timestamp =
3642 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3643#else
3644 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003645 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3646 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003647
3648#endif
3649
Jeff Johnson295189b2012-06-20 16:38:30 -07003650 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3651 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003652
3653#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3654 /* GPS Requirement: need age ie per entry. Using vendor specific. */
3655 /* Assuming this is the last IE, copy at the end */
3656 ie_length -=sizeof(qcom_ie_age);
3657 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
3658 qie_age->element_id = QCOM_VENDOR_IE_ID;
3659 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
3660 qie_age->oui_1 = QCOM_OUI1;
3661 qie_age->oui_2 = QCOM_OUI2;
3662 qie_age->oui_3 = QCOM_OUI3;
3663 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
3664 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
3665#endif
3666
Jeff Johnson295189b2012-06-20 16:38:30 -07003667 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3668
3669 mgmt->frame_control |=
3670 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3671
3672#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3673 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3674 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3675 {
3676 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3677 }
3678 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3679 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3680
3681 {
3682 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3683 }
3684 else
3685 {
3686 kfree(mgmt);
3687 return NULL;
3688 }
3689#else
3690 freq = ieee80211_channel_to_frequency(chan_no);
3691#endif
3692 chan = __ieee80211_get_channel(wiphy, freq);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08003693 /*when the band is changed on the fly using the GUI, three things are done
3694 * 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)
3695 * as part of the scan abort, message willbe queued to PE and we proceed with flushing and changinh the band.
3696 * pe will stop the scanning further and report back the results what ever it had till now by calling the call back function.
3697 * if the time between update band and scandone call back is sufficent enough the band change reflects in SME, SME validates the channels
3698 * and discards the channels correponding to previous band and calls back with zero bss results.
3699 * 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
3700 * all the channels correponding to previous band.this is due to race condition.but those channels are invalid to the new band and so
3701 * this function __ieee80211_get_channel will return NULL.Each time we report scan result with this pointer null warning kernel trace is printed.
3702 * if the scan results contain large number of APs continuosly kernel warning trace is printed and it will lead to apps watch dog bark.
3703 * So drop the bss and continue to next bss.
3704 */
3705 if(chan == NULL)
3706 {
3707 hddLog(VOS_TRACE_LEVEL_INFO, "%s chan pointer is NULL", __func__);
3708 return NULL;
3709 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003710 /*To keep the rssi icon of the connected AP in the scan window
3711 *and the rssi icon of the wireless networks in sync
3712 * */
3713 if (( eConnectionState_Associated ==
3714 pAdapter->sessionCtx.station.conn_info.connState ) &&
3715 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3716 pAdapter->sessionCtx.station.conn_info.bssId,
3717 WNI_CFG_BSSID_LEN)))
3718 {
3719 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3720 rssi = (pAdapter->rssi * 100);
3721 }
3722 else
3723 {
3724 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3725 }
3726
3727 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3728 frame_len, rssi, GFP_KERNEL);
3729 kfree(mgmt);
3730 return bss_status;
3731}
3732
3733/*
3734 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3735 * This function is used to update the BSS data base of CFG8011
3736 */
3737struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3738 tCsrRoamInfo *pRoamInfo
3739 )
3740{
3741 tCsrRoamConnectedProfile roamProfile;
3742 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3743 struct cfg80211_bss *bss = NULL;
3744
3745 ENTER();
3746
3747 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
3748 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
3749
3750 if (NULL != roamProfile.pBssDesc)
3751 {
3752 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
3753 &roamProfile);
3754
3755 if (NULL == bss)
3756 {
3757 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
3758 __func__);
3759 }
3760
3761 sme_RoamFreeConnectProfile(hHal, &roamProfile);
3762 }
3763 else
3764 {
3765 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
3766 __func__);
3767 }
3768 return bss;
3769}
3770
3771/*
3772 * FUNCTION: wlan_hdd_cfg80211_update_bss
3773 */
3774static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
3775 hdd_adapter_t *pAdapter
3776 )
3777{
3778 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3779 tCsrScanResultInfo *pScanResult;
3780 eHalStatus status = 0;
3781 tScanResultHandle pResult;
3782 struct cfg80211_bss *bss_status = NULL;
3783
3784 ENTER();
3785
3786 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3787 {
3788 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3789 return -EAGAIN;
3790 }
3791
3792 /*
3793 * start getting scan results and populate cgf80211 BSS database
3794 */
3795 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
3796
3797 /* no scan results */
3798 if (NULL == pResult)
3799 {
3800 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
3801 return status;
3802 }
3803
3804 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
3805
3806 while (pScanResult)
3807 {
3808 /*
3809 * cfg80211_inform_bss() is not updating ie field of bss entry, if
3810 * entry already exists in bss data base of cfg80211 for that
3811 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
3812 * bss entry instead of cfg80211_inform_bss, But this call expects
3813 * mgmt packet as input. As of now there is no possibility to get
3814 * the mgmt(probe response) frame from PE, converting bss_desc to
3815 * ieee80211_mgmt(probe response) and passing to c
3816 * fg80211_inform_bss_frame.
3817 * */
3818
3819 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
3820 &pScanResult->BssDescriptor);
3821
3822
3823 if (NULL == bss_status)
3824 {
3825 hddLog(VOS_TRACE_LEVEL_INFO,
3826 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
3827 }
3828 else
3829 {
3830 cfg80211_put_bss(bss_status);
3831 }
3832
3833 pScanResult = sme_ScanResultGetNext(hHal, pResult);
3834 }
3835
3836 sme_ScanResultPurge(hHal, pResult);
3837
3838 return 0;
3839}
3840
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003841void
3842hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
3843{
3844 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003845 "%02X:%02X:%02X:%02X:%02X:%02X\n",
3846 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
3847 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003848} /****** end hddPrintMacAddr() ******/
3849
3850void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003851hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003852{
3853 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003854 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
3855 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
3856 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
3857 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003858} /****** end hddPrintPmkId() ******/
3859
3860//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
3861//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
3862
3863//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
3864//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
3865
3866#define dump_bssid(bssid) \
3867 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003868 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
3869 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
3870 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003871 }
3872
3873#define dump_pmkid(pMac, pmkid) \
3874 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003875 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
3876 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
3877 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003878 }
3879
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07003880#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003881/*
3882 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
3883 * This function is used to notify the supplicant of a new PMKSA candidate.
3884 */
3885int wlan_hdd_cfg80211_pmksa_candidate_notify(
3886 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
3887 int index, bool preauth )
3888{
Jeff Johnsone7245742012-09-05 17:12:55 -07003889#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003890 struct net_device *dev = pAdapter->dev;
3891
3892 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07003893 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003894
3895 if( NULL == pRoamInfo )
3896 {
3897 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
3898 return -EINVAL;
3899 }
3900
3901 dump_bssid(pRoamInfo->bssid);
3902 cfg80211_pmksa_candidate_notify(dev, index,
3903 pRoamInfo->bssid, preauth, GFP_KERNEL);
Jeff Johnsone7245742012-09-05 17:12:55 -07003904#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003905 return 0;
3906}
3907#endif //FEATURE_WLAN_LFR
3908
Jeff Johnson295189b2012-06-20 16:38:30 -07003909/*
3910 * FUNCTION: hdd_cfg80211_scan_done_callback
3911 * scanning callback function, called after finishing scan
3912 *
3913 */
3914static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
3915 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
3916{
3917 struct net_device *dev = (struct net_device *) pContext;
3918 //struct wireless_dev *wdev = dev->ieee80211_ptr;
3919 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003920 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3921 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07003922 struct cfg80211_scan_request *req = NULL;
3923 int ret = 0;
3924
3925 ENTER();
3926
3927 hddLog(VOS_TRACE_LEVEL_INFO,
3928 "%s called with halHandle = %p, pContext = %p,"
3929 "scanID = %d, returned status = %d\n",
3930 __func__, halHandle, pContext, (int) scanId, (int) status);
3931
3932 //Block on scan req completion variable. Can't wait forever though.
3933 ret = wait_for_completion_interruptible_timeout(
3934 &pScanInfo->scan_req_completion_event,
3935 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
3936 if (!ret)
3937 {
3938 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003939 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003940 }
3941
3942 if(pScanInfo->mScanPending != VOS_TRUE)
3943 {
3944 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003945 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003946 }
3947
3948 /* Check the scanId */
3949 if (pScanInfo->scanId != scanId)
3950 {
3951 hddLog(VOS_TRACE_LEVEL_INFO,
3952 "%s called with mismatched scanId pScanInfo->scanId = %d "
3953 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
3954 (int) scanId);
3955 }
3956
Jeff Johnson295189b2012-06-20 16:38:30 -07003957 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
3958 pAdapter);
3959
3960 if (0 > ret)
3961 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
3962
3963
3964 /* If any client wait scan result through WEXT
3965 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003966 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07003967 {
3968 /* The other scan request waiting for current scan finish
3969 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003970 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003971 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003972 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003973 }
3974 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003975 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003976 {
3977 struct net_device *dev = pAdapter->dev;
3978 union iwreq_data wrqu;
3979 int we_event;
3980 char *msg;
3981
3982 memset(&wrqu, '\0', sizeof(wrqu));
3983 we_event = SIOCGIWSCAN;
3984 msg = NULL;
3985 wireless_send_event(dev, we_event, &wrqu, msg);
3986 }
3987 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003988 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003989
3990 /* Get the Scan Req */
3991 req = pAdapter->request;
3992
3993 if (!req)
3994 {
3995 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003996 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07003997 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003998 }
3999
4000 /*
4001 * setting up 0, just in case.
4002 */
4003 req->n_ssids = 0;
4004 req->n_channels = 0;
4005 req->ie = 0;
4006
Jeff Johnson295189b2012-06-20 16:38:30 -07004007 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004008 /* Scan is no longer pending */
4009 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004010
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07004011 /*
4012 * cfg80211_scan_done informing NL80211 about completion
4013 * of scanning
4014 */
4015 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004016 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004017
Jeff Johnsone7245742012-09-05 17:12:55 -07004018allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004019 /* release the wake lock at the end of the scan*/
4020 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004021
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004022 /* Acquire wakelock to handle the case where APP's tries to suspend
4023 * immediatly after the driver gets connect request(i.e after scan)
4024 * from supplicant, this result in app's is suspending and not able
4025 * to process the connect request to AP */
4026 hdd_allow_suspend_timeout(100);
4027
Jeff Johnson295189b2012-06-20 16:38:30 -07004028 EXIT();
4029 return 0;
4030}
4031
4032/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004033 * FUNCTION: hdd_isScanAllowed
4034 * Go through each adapter and check if scan allowed
4035 *
4036 */
4037v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
4038{
4039 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4040 hdd_station_ctx_t *pHddStaCtx = NULL;
4041 hdd_adapter_t *pAdapter = NULL;
4042 VOS_STATUS status = 0;
4043 v_U8_t staId = 0;
4044 v_U8_t *staMac = NULL;
4045
4046 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4047
4048 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4049 {
4050 pAdapter = pAdapterNode->pAdapter;
4051
4052 if( pAdapter )
4053 {
4054 hddLog(VOS_TRACE_LEVEL_INFO,
4055 "%s: Adapter with device mode %d exists",
4056 __func__, pAdapter->device_mode);
4057 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4058 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4059 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
4060 {
4061 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4062 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
4063 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
4064 {
4065 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
4066 hddLog(VOS_TRACE_LEVEL_ERROR,
4067 "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the "
4068 "middle of WPS/EAPOL exchange.", __func__,
4069 staMac[0], staMac[1], staMac[2],
4070 staMac[3], staMac[4], staMac[5]);
4071 return VOS_FALSE;
4072 }
4073 }
4074 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
4075 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
4076 {
4077 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
4078 {
4079 if ((pAdapter->aStaInfo[staId].isUsed) &&
4080 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
4081 {
4082 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
4083
4084 hddLog(VOS_TRACE_LEVEL_ERROR,
4085 "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the "
4086 "middle of WPS/EAPOL exchange.", __func__,
4087 staMac[0], staMac[1], staMac[2],
4088 staMac[3], staMac[4], staMac[5]);
4089 return VOS_FALSE;
4090 }
4091 }
4092 }
4093 }
4094 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4095 pAdapterNode = pNext;
4096 }
4097 hddLog(VOS_TRACE_LEVEL_INFO,
4098 "%s: Scan allowed", __func__);
4099 return VOS_TRUE;
4100}
4101
4102/*
Jeff Johnson295189b2012-06-20 16:38:30 -07004103 * FUNCTION: wlan_hdd_cfg80211_scan
4104 * this scan respond to scan trigger and update cfg80211 scan database
4105 * later, scan dump command can be used to recieve scan results
4106 */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08004107int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
4108#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4109 struct net_device *dev,
4110#endif
4111 struct cfg80211_scan_request *request)
4112{
4113#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4114 struct net_device *dev = request->wdev->netdev;
4115#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004116 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4117 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4118 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4119 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
4120 tCsrScanRequest scanRequest;
4121 tANI_U8 *channelList = NULL, i;
4122 v_U32_t scanId = 0;
4123 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004124 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004125#ifdef WLAN_FEATURE_P2P
4126 v_U8_t* pP2pIe = NULL;
4127#endif
4128
4129 ENTER();
4130
4131 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4132 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004133
4134 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
4135 (eConnectionState_Connecting ==
4136 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) )
4137 {
4138 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004139 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
4140 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004141 return -EBUSY;
4142 }
4143
Jeff Johnson295189b2012-06-20 16:38:30 -07004144#ifdef WLAN_BTAMP_FEATURE
4145 //Scan not supported when AMP traffic is on.
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004146 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
Jeff Johnson295189b2012-06-20 16:38:30 -07004147 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004148 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004149 "%s: No scanning when AMP is on", __func__);
4150 return -EOPNOTSUPP;
4151 }
4152#endif
4153 //Scan on any other interface is not supported.
4154 if( pAdapter->device_mode == WLAN_HDD_SOFTAP )
4155 {
4156 hddLog(VOS_TRACE_LEVEL_ERROR,
4157 "%s: Not scanning on device_mode = %d",
4158 __func__, pAdapter->device_mode);
4159 return -EOPNOTSUPP;
4160 }
4161
4162 if (TRUE == pScanInfo->mScanPending)
4163 {
4164 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
4165 return -EBUSY;
4166 }
4167
4168 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4169 {
4170 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4171 "%s:LOGP in Progress. Ignore!!!", __func__);
4172 return -EAGAIN;
4173 }
4174
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07004175 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
4176 {
4177 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4178 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
4179 return -EAGAIN;
4180 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004181 //Don't Allow Scan and return busy if Remain On
4182 //Channel and action frame is pending
4183 //Otherwise Cancel Remain On Channel and allow Scan
4184 //If no action frame pending
4185 if(0 != wlan_hdd_check_remain_on_channel(pAdapter))
4186 {
4187 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
4188 return -EBUSY;
4189 }
4190
Jeff Johnson295189b2012-06-20 16:38:30 -07004191 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
4192 {
4193 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08004194 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004195 return -EAGAIN;
4196 }
4197 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
4198 {
4199 hddLog(VOS_TRACE_LEVEL_WARN,
4200 "%s: MAX TM Level Scan not allowed", __func__);
4201 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4202 return -EBUSY;
4203 }
4204 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4205
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004206 /* Check if scan is allowed at this point of time.
4207 */
4208 if (!hdd_isScanAllowed(pHddCtx))
4209 {
4210 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
4211 return -EBUSY;
4212 }
4213
Jeff Johnson295189b2012-06-20 16:38:30 -07004214 vos_mem_zero( &scanRequest, sizeof(scanRequest));
4215
4216 if (NULL != request)
4217 {
4218 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
4219 (int)request->n_ssids);
4220
4221 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
4222 * Becasue of this, driver is assuming that this is not wildcard scan and so
4223 * is not aging out the scan results.
4224 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07004225 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07004226 {
4227 request->n_ssids = 0;
4228 }
4229
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004230 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07004231 {
4232 tCsrSSIDInfo *SsidInfo;
4233 int j;
4234 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
4235 /* Allocate num_ssid tCsrSSIDInfo structure */
4236 SsidInfo = scanRequest.SSIDs.SSIDList =
4237 ( tCsrSSIDInfo *)vos_mem_malloc(
4238 request->n_ssids*sizeof(tCsrSSIDInfo));
4239
4240 if(NULL == scanRequest.SSIDs.SSIDList)
4241 {
4242 hddLog(VOS_TRACE_LEVEL_ERROR,
4243 "memory alloc failed SSIDInfo buffer");
4244 return -ENOMEM;
4245 }
4246
4247 /* copy all the ssid's and their length */
4248 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
4249 {
4250 /* get the ssid length */
4251 SsidInfo->SSID.length = request->ssids[j].ssid_len;
4252 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
4253 SsidInfo->SSID.length);
4254 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
4255 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
4256 j, SsidInfo->SSID.ssId);
4257 }
4258 /* set the scan type to active */
4259 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4260 }
4261 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4262 {
4263 /* set the scan type to active */
4264 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4265 }
4266 else
4267 {
4268 /*Set the scan type to default type, in this case it is ACTIVE*/
4269 scanRequest.scanType = pScanInfo->scan_mode;
4270 }
4271 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
4272 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4273 }
4274 else
4275 {
4276 /* set the scan type to active */
4277 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4278 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4279
4280 /* set min and max channel time to zero */
4281 scanRequest.minChnTime = 0;
4282 scanRequest.maxChnTime = 0;
4283 }
4284
4285 /* set BSSType to default type */
4286 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4287
4288 /*TODO: scan the requested channels only*/
4289
4290 /*Right now scanning all the channels */
4291 if( request )
4292 {
4293 if( request->n_channels )
4294 {
4295 channelList = vos_mem_malloc( request->n_channels );
4296 if( NULL == channelList )
4297 {
4298 status = -ENOMEM;
4299 goto free_mem;
4300 }
4301
4302 for( i = 0 ; i < request->n_channels ; i++ )
4303 channelList[i] = request->channels[i]->hw_value;
4304 }
4305
4306 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4307 scanRequest.ChannelInfo.ChannelList = channelList;
4308
4309 /* set requestType to full scan */
4310 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004311
4312 /* Flush the scan results(only p2p beacons) for STA scan and P2P
4313 * search (Flush on both full scan and social scan but not on single
4314 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
4315 */
4316
4317 /* Supplicant does single channel scan after 8-way handshake
4318 * and in that case driver shoudnt flush scan results. If
4319 * driver flushes the scan results here and unfortunately if
4320 * the AP doesnt respond to our probe req then association
4321 * fails which is not desired
4322 */
4323
4324 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4325 {
4326 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4327 pAdapter->sessionId );
4328 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004329
4330 if( request->ie_len )
4331 {
4332 /* save this for future association (join requires this) */
4333 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4334 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4335 pScanInfo->scanAddIE.length = request->ie_len;
4336
4337 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004338 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4339 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004340 )
4341 {
4342 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4343 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4344 }
4345
4346 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4347 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4348
4349#ifdef WLAN_FEATURE_P2P
4350 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4351 request->ie_len);
4352 if (pP2pIe != NULL)
4353 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004354#ifdef WLAN_FEATURE_P2P_DEBUG
4355 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4356 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4357 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4358 {
4359 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4360 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4361 "Go nego completed to Connection is started");
4362 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4363 "for 8way Handshake");
4364 }
4365 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4366 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4367 {
4368 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4369 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4370 "Disconnected state to Connection is started");
4371 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4372 "for 4way Handshake");
4373 }
4374#endif
4375
Jeff Johnsone7245742012-09-05 17:12:55 -07004376 /* no_cck will be set during p2p find to disable 11b rates */
4377 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004378 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004379 hddLog(VOS_TRACE_LEVEL_INFO,
4380 "%s: This is a P2P Search", __func__);
4381 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004382
Jeff Johnsone7245742012-09-05 17:12:55 -07004383 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4384 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004385 /* set requestType to P2P Discovery */
4386 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004387 }
4388
4389 /*
4390 Skip Dfs Channel in case of P2P Search
4391 if it is set in ini file
4392 */
4393 if(cfg_param->skipDfsChnlInP2pSearch)
4394 {
4395 scanRequest.skipDfsChnlInP2pSearch = 1;
4396 }
4397 else
4398 {
4399 scanRequest.skipDfsChnlInP2pSearch = 0;
4400 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004401
Jeff Johnson295189b2012-06-20 16:38:30 -07004402 }
4403 }
4404#endif
4405 }
4406 }
4407
4408 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4409
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004410 /* acquire the wakelock to avoid the apps suspend during the scan. To
4411 * address the following issues.
4412 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4413 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4414 * for long time, this result in apps running at full power for long time.
4415 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4416 * be stuck in full power because of resume BMPS
4417 */
4418 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004419
4420 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004421 pAdapter->sessionId, &scanRequest, &scanId,
4422 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004423
Jeff Johnson295189b2012-06-20 16:38:30 -07004424 if (eHAL_STATUS_SUCCESS != status)
4425 {
4426 hddLog(VOS_TRACE_LEVEL_ERROR,
4427 "%s: sme_ScanRequest returned error %d", __func__, status);
4428 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004429 if(eHAL_STATUS_RESOURCES == status)
4430 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004431 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 -07004432 status = -EBUSY;
4433 } else {
4434 status = -EIO;
4435 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004436 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004437 goto free_mem;
4438 }
4439
4440 pScanInfo->mScanPending = TRUE;
4441 pAdapter->request = request;
4442 pScanInfo->scanId = scanId;
4443
4444 complete(&pScanInfo->scan_req_completion_event);
4445
4446free_mem:
4447 if( scanRequest.SSIDs.SSIDList )
4448 {
4449 vos_mem_free(scanRequest.SSIDs.SSIDList);
4450 }
4451
4452 if( channelList )
4453 vos_mem_free( channelList );
4454
4455 EXIT();
4456
4457 return status;
4458}
4459
4460/*
4461 * FUNCTION: wlan_hdd_cfg80211_connect_start
4462 * This function is used to start the association process
4463 */
4464int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004465 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004466{
4467 int status = 0;
4468 hdd_wext_state_t *pWextState;
4469 v_U32_t roamId;
4470 tCsrRoamProfile *pRoamProfile;
4471 eMib_dot11DesiredBssType connectedBssType;
4472 eCsrAuthType RSNAuthType;
4473
4474 ENTER();
4475
4476 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4477
4478 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4479 {
4480 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4481 return -EINVAL;
4482 }
4483
4484 pRoamProfile = &pWextState->roamProfile;
4485
4486 if (pRoamProfile)
4487 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004488 int ret = 0;
4489 hdd_station_ctx_t *pHddStaCtx;
4490 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4491 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4492
4493 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4494 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4495 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004496 {
4497 /* Issue disconnect to CSR */
4498 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4499 if( eHAL_STATUS_SUCCESS ==
4500 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4501 pAdapter->sessionId,
4502 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4503 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004504 ret = wait_for_completion_interruptible_timeout(
4505 &pAdapter->disconnect_comp_var,
4506 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4507 if (0 == ret)
4508 {
4509 VOS_ASSERT(0);
4510 }
4511 }
4512 }
4513 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4514 {
4515 ret = wait_for_completion_interruptible_timeout(
4516 &pAdapter->disconnect_comp_var,
4517 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4518 if (0 == ret)
4519 {
4520 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004521 }
4522 }
4523
4524 if (HDD_WMM_USER_MODE_NO_QOS ==
4525 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4526 {
4527 /*QoS not enabled in cfg file*/
4528 pRoamProfile->uapsd_mask = 0;
4529 }
4530 else
4531 {
4532 /*QoS enabled, update uapsd mask from cfg file*/
4533 pRoamProfile->uapsd_mask =
4534 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4535 }
4536
4537 pRoamProfile->SSIDs.numOfSSIDs = 1;
4538 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4539 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
4540 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
4541 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4542 ssid, ssid_len);
4543
4544 if (bssid)
4545 {
4546 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4547 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4548 WNI_CFG_BSSID_LEN);
4549 /* Save BSSID in seperate variable as well, as RoamProfile
4550 BSSID is getting zeroed out in the association process. And in
4551 case of join failure we should send valid BSSID to supplicant
4552 */
4553 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4554 WNI_CFG_BSSID_LEN);
4555 }
4556
4557 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4558 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4559 {
4560 /*set gen ie*/
4561 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4562 /*set auth*/
4563 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4564 }
4565 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4566 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4567 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4568 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4569 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4570 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4571 )
4572 {
4573 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4574 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4575 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4576 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4577 eCSR_AUTH_TYPE_AUTOSWITCH;
4578 pWextState->roamProfile.AuthType.authType[0] =
4579 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4580 }
4581#ifdef FEATURE_WLAN_WAPI
4582 if (pAdapter->wapi_info.nWapiMode)
4583 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004584 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004585 switch (pAdapter->wapi_info.wapiAuthMode)
4586 {
4587 case WAPI_AUTH_MODE_PSK:
4588 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004589 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004590 pAdapter->wapi_info.wapiAuthMode);
4591 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4592 break;
4593 }
4594 case WAPI_AUTH_MODE_CERT:
4595 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004596 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004597 pAdapter->wapi_info.wapiAuthMode);
4598 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4599 break;
4600 }
4601 } // End of switch
4602 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4603 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4604 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004605 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004606 pRoamProfile->AuthType.numEntries = 1;
4607 pRoamProfile->EncryptionType.numEntries = 1;
4608 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4609 pRoamProfile->mcEncryptionType.numEntries = 1;
4610 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4611 }
4612 }
4613#endif /* FEATURE_WLAN_WAPI */
4614 pRoamProfile->csrPersona = pAdapter->device_mode;
4615
Jeff Johnson32d95a32012-09-10 13:15:23 -07004616 if( operatingChannel )
4617 {
4618 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4619 pRoamProfile->ChannelInfo.numOfChannels = 1;
4620 }
4621
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004622 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
4623 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
4624 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
4625 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004626 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
4627 */
4628 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4629 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
4630 eConnectionState_Connecting);
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004631
Jeff Johnson295189b2012-06-20 16:38:30 -07004632 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4633 pAdapter->sessionId, pRoamProfile, &roamId);
4634
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004635 if( (eHAL_STATUS_SUCCESS != status) &&
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304636 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
4637
4638 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004639 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
4640 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
4641 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304642 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004643 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304644 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004645
4646 pRoamProfile->ChannelInfo.ChannelList = NULL;
4647 pRoamProfile->ChannelInfo.numOfChannels = 0;
4648
Jeff Johnson295189b2012-06-20 16:38:30 -07004649 }
4650 else
4651 {
4652 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4653 return -EINVAL;
4654 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004655 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004656 return status;
4657}
4658
4659/*
4660 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4661 * This function is used to set the authentication type (OPEN/SHARED).
4662 *
4663 */
4664static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4665 enum nl80211_auth_type auth_type)
4666{
4667 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4668 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4669
4670 ENTER();
4671
4672 /*set authentication type*/
4673 switch (auth_type)
4674 {
4675 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4676 case NL80211_AUTHTYPE_AUTOMATIC:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07004677#ifdef WLAN_FEATURE_VOWIFI_11R
4678 case NL80211_AUTHTYPE_FT:
4679#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07004680 hddLog(VOS_TRACE_LEVEL_INFO,
4681 "%s: set authentication type to OPEN", __func__);
4682 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4683 break;
4684
4685 case NL80211_AUTHTYPE_SHARED_KEY:
4686 hddLog(VOS_TRACE_LEVEL_INFO,
4687 "%s: set authentication type to SHARED", __func__);
4688 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4689 break;
4690#ifdef FEATURE_WLAN_CCX
4691 case NL80211_AUTHTYPE_NETWORK_EAP:
4692 hddLog(VOS_TRACE_LEVEL_INFO,
4693 "%s: set authentication type to CCKM WPA", __func__);
4694 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4695 break;
4696#endif
4697
4698
4699 default:
4700 hddLog(VOS_TRACE_LEVEL_ERROR,
4701 "%s: Unsupported authentication type %d", __func__,
4702 auth_type);
4703 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4704 return -EINVAL;
4705 }
4706
4707 pWextState->roamProfile.AuthType.authType[0] =
4708 pHddStaCtx->conn_info.authType;
4709 return 0;
4710}
4711
4712/*
4713 * FUNCTION: wlan_hdd_set_akm_suite
4714 * This function is used to set the key mgmt type(PSK/8021x).
4715 *
4716 */
4717static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
4718 u32 key_mgmt
4719 )
4720{
4721 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4722 ENTER();
4723
4724 /*set key mgmt type*/
4725 switch(key_mgmt)
4726 {
4727 case WLAN_AKM_SUITE_PSK:
4728 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
4729 __func__);
4730 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
4731 break;
4732
4733 case WLAN_AKM_SUITE_8021X:
4734 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
4735 __func__);
4736 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
4737 break;
4738#ifdef FEATURE_WLAN_CCX
4739#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
4740#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
4741 case WLAN_AKM_SUITE_CCKM:
4742 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
4743 __func__);
4744 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
4745 break;
4746#endif
4747
4748 default:
4749 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
4750 __func__, key_mgmt);
4751 return -EINVAL;
4752
4753 }
4754 return 0;
4755}
4756
4757/*
4758 * FUNCTION: wlan_hdd_cfg80211_set_cipher
4759 * This function is used to set the encryption type
4760 * (NONE/WEP40/WEP104/TKIP/CCMP).
4761 */
4762static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
4763 u32 cipher,
4764 bool ucast
4765 )
4766{
4767 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4768 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4769 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4770
4771 ENTER();
4772
4773 if (!cipher)
4774 {
4775 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
4776 __func__, cipher);
4777 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4778 }
4779 else
4780 {
4781
4782 /*set encryption method*/
4783 switch (cipher)
4784 {
4785 case IW_AUTH_CIPHER_NONE:
4786 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4787 break;
4788
4789 case WLAN_CIPHER_SUITE_WEP40:
4790 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4791 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4792 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
4793 else
4794 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4795 break;
4796
4797 case WLAN_CIPHER_SUITE_WEP104:
4798 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4799 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4800 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
4801 else
4802 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
4803 break;
4804
4805 case WLAN_CIPHER_SUITE_TKIP:
4806 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
4807 break;
4808
4809 case WLAN_CIPHER_SUITE_CCMP:
4810 encryptionType = eCSR_ENCRYPT_TYPE_AES;
4811 break;
4812#ifdef FEATURE_WLAN_WAPI
4813 case WLAN_CIPHER_SUITE_SMS4:
4814 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
4815 break;
4816#endif
4817
4818#ifdef FEATURE_WLAN_CCX
4819 case WLAN_CIPHER_SUITE_KRK:
4820 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
4821 break;
4822#endif
4823 default:
4824 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
4825 __func__, cipher);
4826 return -EOPNOTSUPP;
4827 }
4828 }
4829
4830 if (ucast)
4831 {
4832 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
4833 __func__, encryptionType);
4834 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
4835 pWextState->roamProfile.EncryptionType.numEntries = 1;
4836 pWextState->roamProfile.EncryptionType.encryptionType[0] =
4837 encryptionType;
4838 }
4839 else
4840 {
4841 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
4842 __func__, encryptionType);
4843 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
4844 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
4845 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
4846 }
4847
4848 return 0;
4849}
4850
4851
4852/*
4853 * FUNCTION: wlan_hdd_cfg80211_set_ie
4854 * This function is used to parse WPA/RSN IE's.
4855 */
4856int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
4857 u8 *ie,
4858 size_t ie_len
4859 )
4860{
4861 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4862 u8 *genie = ie;
4863 v_U16_t remLen = ie_len;
4864#ifdef FEATURE_WLAN_WAPI
4865 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
4866 u16 *tmp;
4867 v_U16_t akmsuiteCount;
4868 int *akmlist;
4869#endif
4870 ENTER();
4871
4872 /* clear previous assocAddIE */
4873 pWextState->assocAddIE.length = 0;
4874 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
4875
4876 while (remLen >= 2)
4877 {
4878 v_U16_t eLen = 0;
4879 v_U8_t elementId;
4880 elementId = *genie++;
4881 eLen = *genie++;
4882 remLen -= 2;
4883
4884 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
4885 __func__, elementId, eLen);
4886
4887 switch ( elementId )
4888 {
4889 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004890 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 -07004891 {
4892 hddLog(VOS_TRACE_LEVEL_ERROR,
4893 "%s: Invalid WPA IE", __func__);
4894 return -EINVAL;
4895 }
4896 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
4897 {
4898 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4899 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
4900 __func__, eLen + 2);
4901
4902 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4903 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004904 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
4905 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004906 VOS_ASSERT(0);
4907 return -ENOMEM;
4908 }
4909 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4910 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4911 pWextState->assocAddIE.length += eLen + 2;
4912
4913 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
4914 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4915 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4916 }
4917 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
4918 {
4919 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
4920 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4921 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
4922 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
4923 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
4924 }
4925#ifdef WLAN_FEATURE_P2P
4926 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
4927 P2P_OUI_TYPE_SIZE))
4928 /*Consider P2P IE, only for P2P Client */
4929 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4930 {
4931 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4932 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
4933 __func__, eLen + 2);
4934
4935 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4936 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004937 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4938 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004939 VOS_ASSERT(0);
4940 return -ENOMEM;
4941 }
4942 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4943 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4944 pWextState->assocAddIE.length += eLen + 2;
4945
4946 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4947 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4948 }
4949#endif
4950#ifdef WLAN_FEATURE_WFD
4951 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
4952 WFD_OUI_TYPE_SIZE))
4953 /*Consider WFD IE, only for P2P Client */
4954 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4955 {
4956 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4957 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
4958 __func__, eLen + 2);
4959
4960 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4961 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004962 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4963 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004964 VOS_ASSERT(0);
4965 return -ENOMEM;
4966 }
4967 // WFD IE is saved to Additional IE ; it should be accumulated to handle
4968 // WPS IE + P2P IE + WFD IE
4969 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4970 pWextState->assocAddIE.length += eLen + 2;
4971
4972 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4973 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4974 }
4975#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004976 /* Appending HS 2.0 Indication Element in Assiciation Request */
4977 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004978 HS20_OUI_TYPE_SIZE)) )
4979 {
4980 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4981 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
4982 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004983
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004984 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4985 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004986 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4987 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004988 VOS_ASSERT(0);
4989 return -ENOMEM;
4990 }
4991 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4992 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004993
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004994 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4995 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4996 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004997
Jeff Johnson295189b2012-06-20 16:38:30 -07004998 break;
4999 case DOT11F_EID_RSN:
5000 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
5001 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5002 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
5003 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
5004 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
5005 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005006 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
5007 case DOT11F_EID_EXTCAP:
5008 {
5009 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5010 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
5011 __func__, eLen + 2);
5012
5013 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5014 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005015 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5016 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005017 VOS_ASSERT(0);
5018 return -ENOMEM;
5019 }
5020 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5021 pWextState->assocAddIE.length += eLen + 2;
5022
5023 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5024 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5025 break;
5026 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005027#ifdef FEATURE_WLAN_WAPI
5028 case WLAN_EID_WAPI:
5029 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
5030 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
5031 pAdapter->wapi_info.nWapiMode);
5032 tmp = (u16 *)ie;
5033 tmp = tmp + 2; // Skip element Id and Len, Version
5034 akmsuiteCount = WPA_GET_LE16(tmp);
5035 tmp = tmp + 1;
5036 akmlist = (int *)(tmp);
5037 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
5038 {
5039 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
5040 }
5041 else
5042 {
5043 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
5044 VOS_ASSERT(0);
5045 return -EINVAL;
5046 }
5047
5048 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
5049 {
5050 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005051 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005052 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
5053 }
5054 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
5055 {
5056 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005057 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005058 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
5059 }
5060 break;
5061#endif
5062 default:
5063 hddLog (VOS_TRACE_LEVEL_ERROR,
5064 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005065 /* when Unknown IE is received we should break and continue
5066 * to the next IE in the buffer instead we were returning
5067 * so changing this to break */
5068 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005069 }
5070 genie += eLen;
5071 remLen -= eLen;
5072 }
5073 EXIT();
5074 return 0;
5075}
5076
5077/*
5078 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5079 * This function is used to initialize the security
5080 * parameters during connect operation.
5081 */
5082int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
5083 struct cfg80211_connect_params *req
5084 )
5085{
5086 int status = 0;
5087 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5088 ENTER();
5089
5090 /*set wpa version*/
5091 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5092
5093 if (req->crypto.wpa_versions)
5094 {
5095 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
5096 && ( (req->ie_len)
5097 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
5098 // Make sure that it is including a WPA IE.
5099 /* Currently NL is putting WPA version 1 even for open,
5100 * since p2p ie is also put in same buffer.
5101 * */
5102 {
5103 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5104 }
5105 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
5106 {
5107 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5108 }
5109 }
5110
5111 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
5112 pWextState->wpaVersion);
5113
5114 /*set authentication type*/
5115 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
5116
5117 if (0 > status)
5118 {
5119 hddLog(VOS_TRACE_LEVEL_ERROR,
5120 "%s: failed to set authentication type ", __func__);
5121 return status;
5122 }
5123
5124 /*set key mgmt type*/
5125 if (req->crypto.n_akm_suites)
5126 {
5127 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
5128 if (0 > status)
5129 {
5130 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
5131 __func__);
5132 return status;
5133 }
5134 }
5135
5136 /*set pairwise cipher type*/
5137 if (req->crypto.n_ciphers_pairwise)
5138 {
5139 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
5140 req->crypto.ciphers_pairwise[0], true);
5141 if (0 > status)
5142 {
5143 hddLog(VOS_TRACE_LEVEL_ERROR,
5144 "%s: failed to set unicast cipher type", __func__);
5145 return status;
5146 }
5147 }
5148 else
5149 {
5150 /*Reset previous cipher suite to none*/
5151 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
5152 if (0 > status)
5153 {
5154 hddLog(VOS_TRACE_LEVEL_ERROR,
5155 "%s: failed to set unicast cipher type", __func__);
5156 return status;
5157 }
5158 }
5159
5160 /*set group cipher type*/
5161 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
5162 false);
5163
5164 if (0 > status)
5165 {
5166 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
5167 __func__);
5168 return status;
5169 }
5170
5171 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
5172 if (req->ie_len)
5173 {
5174 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
5175 if ( 0 > status)
5176 {
5177 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
5178 __func__);
5179 return status;
5180 }
5181 }
5182
5183 /*incase of WEP set default key information*/
5184 if (req->key && req->key_len)
5185 {
5186 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
5187 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
5188 )
5189 {
5190 if ( IW_AUTH_KEY_MGMT_802_1X
5191 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
5192 {
5193 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
5194 __func__);
5195 return -EOPNOTSUPP;
5196 }
5197 else
5198 {
5199 u8 key_len = req->key_len;
5200 u8 key_idx = req->key_idx;
5201
5202 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
5203 && (CSR_MAX_NUM_KEY > key_idx)
5204 )
5205 {
5206 hddLog(VOS_TRACE_LEVEL_INFO,
5207 "%s: setting default wep key, key_idx = %hu key_len %hu",
5208 __func__, key_idx, key_len);
5209 vos_mem_copy(
5210 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
5211 req->key, key_len);
5212 pWextState->roamProfile.Keys.KeyLength[key_idx] =
5213 (u8)key_len;
5214 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
5215 }
5216 }
5217 }
5218 }
5219
5220 return status;
5221}
5222
5223/*
5224 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5225 * This function is used to initialize the security
5226 * parameters during connect operation.
5227 */
5228static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
5229 struct net_device *ndev,
5230 struct cfg80211_connect_params *req
5231 )
5232{
5233 int status = 0;
5234 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
5235 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
5236 hdd_context_t *pHddCtx = NULL;
5237
5238 ENTER();
5239
5240 hddLog(VOS_TRACE_LEVEL_INFO,
5241 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5242
5243 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5244 {
5245 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5246 "%s:LOGP in Progress. Ignore!!!", __func__);
5247 return -EAGAIN;
5248 }
5249
5250#ifdef WLAN_BTAMP_FEATURE
5251 //Infra connect not supported when AMP traffic is on.
5252 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
5253 {
5254 hddLog(VOS_TRACE_LEVEL_ERROR,
5255 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005256 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07005257 }
5258#endif
5259 /*initialise security parameters*/
5260 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
5261
5262 if ( 0 > status)
5263 {
5264 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
5265 __func__);
5266 return status;
5267 }
5268
5269 //If Device Mode is Station Concurrent Sessions Exit BMps
Jeff Johnsona8a1a482012-12-12 16:49:33 -08005270 //P2P Mode will be taken care in Open/close adapter
Jeff Johnson295189b2012-06-20 16:38:30 -07005271 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
5272 (vos_concurrent_sessions_running()))
5273 {
5274 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5275
5276 if (NULL != pVosContext)
5277 {
5278 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5279 if(NULL != pHddCtx)
5280 {
5281 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
5282 }
5283 }
5284 }
5285
Mohit Khanna765234a2012-09-11 15:08:35 -07005286 if ( req->channel )
5287 {
5288 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5289 req->ssid_len, req->bssid,
5290 req->channel->hw_value);
5291 }
5292 else
5293 {
5294 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5295 req->ssid_len, req->bssid,
5296 0);
5297 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005298
5299 if (0 > status)
5300 {
5301 //ReEnable BMPS if disabled
5302 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5303 (NULL != pHddCtx))
5304 {
5305 //ReEnable Bmps and Imps back
5306 hdd_enable_bmps_imps(pHddCtx);
5307 }
5308
5309 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5310 return status;
5311 }
5312 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
5313 EXIT();
5314 return status;
5315}
5316
5317
5318/*
5319 * FUNCTION: wlan_hdd_cfg80211_disconnect
5320 * This function is used to issue a disconnect request to SME
5321 */
5322static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
5323 struct net_device *dev,
5324 u16 reason
5325 )
5326{
5327 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5328 tCsrRoamProfile *pRoamProfile =
5329 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
5330 int status = 0;
5331 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005332#ifdef FEATURE_WLAN_TDLS
5333 tANI_U8 staIdx;
5334#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005335
5336 ENTER();
5337
5338 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
5339 __func__,pAdapter->device_mode);
5340
5341 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5342 __func__, reason);
5343
5344 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
5345 {
5346 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5347 "%s:LOGP in Progress. Ignore!!!",__func__);
5348 return -EAGAIN;
5349 }
5350 if (NULL != pRoamProfile)
5351 {
5352 /*issue disconnect request to SME, if station is in connected state*/
5353 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
5354 {
5355 eCsrRoamDisconnectReason reasonCode =
5356 eCSR_DISCONNECT_REASON_UNSPECIFIED;
5357 switch(reason)
5358 {
5359 case WLAN_REASON_MIC_FAILURE:
5360 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
5361 break;
5362
5363 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
5364 case WLAN_REASON_DISASSOC_AP_BUSY:
5365 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
5366 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
5367 break;
5368
5369 case WLAN_REASON_PREV_AUTH_NOT_VALID:
5370 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
5371 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
5372 break;
5373
5374 case WLAN_REASON_DEAUTH_LEAVING:
5375 default:
5376 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
5377 break;
5378 }
5379 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5380 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
5381 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5382
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005383#ifdef FEATURE_WLAN_TDLS
5384 /* First clean up the tdls peers if any */
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005385 for (staIdx = 1 ; staIdx <= HDD_MAX_NUM_TDLS_STA; staIdx++)
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005386 {
5387 if (pHddStaCtx->conn_info.staId[staIdx])
5388 {
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005389 uint8 *mac;
5390 mac = pHddStaCtx->conn_info.peerMacAddress[staIdx].bytes;
5391 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
5392 "%s: call sme_DeleteTdlsPeerSta staId %d sessionId %d %02x:%02x:%02x:%02x:%02x:%02x",
5393 __func__, pHddStaCtx->conn_info.staId[staIdx], pAdapter->sessionId,
5394 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] );
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005395 sme_DeleteTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
5396 pAdapter->sessionId,
5397 pHddStaCtx->conn_info.peerMacAddress[staIdx].bytes);
5398 }
5399 }
5400#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005401 /*issue disconnect*/
5402 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5403 pAdapter->sessionId, reasonCode);
5404
5405 if ( 0 != status)
5406 {
5407 hddLog(VOS_TRACE_LEVEL_ERROR,
5408 "%s csrRoamDisconnect failure, returned %d \n",
5409 __func__, (int)status );
5410 return -EINVAL;
5411 }
5412
5413 wait_for_completion_interruptible_timeout(
5414 &pAdapter->disconnect_comp_var,
5415 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5416
5417
5418 /*stop tx queues*/
5419 netif_tx_disable(dev);
5420 netif_carrier_off(dev);
5421 }
5422 }
5423 else
5424 {
5425 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
5426 }
5427
5428 return status;
5429}
5430
5431/*
5432 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
5433 * This function is used to initialize the security
5434 * settings in IBSS mode.
5435 */
5436static int wlan_hdd_cfg80211_set_privacy_ibss(
5437 hdd_adapter_t *pAdapter,
5438 struct cfg80211_ibss_params *params
5439 )
5440{
5441 int status = 0;
5442 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5443 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5444 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5445
5446 ENTER();
5447
5448 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5449
5450 if (params->ie_len && ( NULL != params->ie) )
5451 {
5452 if (WLAN_EID_RSN == params->ie[0])
5453 {
5454 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5455 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5456 }
5457 else
5458 {
5459 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5460 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5461 }
5462 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
5463
5464 if (0 > status)
5465 {
5466 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
5467 __func__);
5468 return status;
5469 }
5470 }
5471
5472 pWextState->roamProfile.AuthType.authType[0] =
5473 pHddStaCtx->conn_info.authType =
5474 eCSR_AUTH_TYPE_OPEN_SYSTEM;
5475
5476 if (params->privacy)
5477 {
5478 /* Security enabled IBSS, At this time there is no information available
5479 * about the security paramters, so initialise the encryption type to
5480 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
5481 * The correct security parameters will be updated later in
5482 * wlan_hdd_cfg80211_add_key */
5483 /* Hal expects encryption type to be set inorder
5484 *enable privacy bit in beacons */
5485
5486 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5487 }
5488
5489 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5490 pWextState->roamProfile.EncryptionType.numEntries = 1;
5491 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
5492
5493 return status;
5494}
5495
5496/*
5497 * FUNCTION: wlan_hdd_cfg80211_join_ibss
5498 * This function is used to create/join an IBSS
5499 */
5500static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
5501 struct net_device *dev,
5502 struct cfg80211_ibss_params *params
5503 )
5504{
5505 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5506 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5507 tCsrRoamProfile *pRoamProfile;
5508 int status;
5509 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5510
5511 ENTER();
5512
5513 hddLog(VOS_TRACE_LEVEL_INFO,
5514 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5515
5516 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5517 {
5518 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5519 "%s:LOGP in Progress. Ignore!!!", __func__);
5520 return -EAGAIN;
5521 }
5522
5523 if (NULL == pWextState)
5524 {
5525 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5526 __func__);
5527 return -EIO;
5528 }
5529
5530 pRoamProfile = &pWextState->roamProfile;
5531
5532 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
5533 {
5534 hddLog (VOS_TRACE_LEVEL_ERROR,
5535 "%s Interface type is not set to IBSS \n", __func__);
5536 return -EINVAL;
5537 }
5538
5539 /* Set Channel */
5540 if (NULL != params->channel)
5541 {
5542 u8 channelNum;
5543 if (IEEE80211_BAND_5GHZ == params->channel->band)
5544 {
5545 hddLog(VOS_TRACE_LEVEL_ERROR,
5546 "%s: IBSS join is called with unsupported band %d",
5547 __func__, params->channel->band);
5548 return -EOPNOTSUPP;
5549 }
5550
5551 /* Get channel number */
5552 channelNum =
5553 ieee80211_frequency_to_channel(params->channel->center_freq);
5554
5555 /*TODO: use macro*/
5556 if (14 >= channelNum)
5557 {
5558 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5559 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5560 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5561 int indx;
5562
5563 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5564 validChan, &numChans))
5565 {
5566 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
5567 __func__);
5568 return -EOPNOTSUPP;
5569 }
5570
5571 for (indx = 0; indx < numChans; indx++)
5572 {
5573 if (channelNum == validChan[indx])
5574 {
5575 break;
5576 }
5577 }
5578 if (indx >= numChans)
5579 {
5580 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
5581 __func__, channelNum);
5582 return -EINVAL;
5583 }
5584 /* Set the Operational Channel */
5585 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
5586 channelNum);
5587 pRoamProfile->ChannelInfo.numOfChannels = 1;
5588 pHddStaCtx->conn_info.operationChannel = channelNum;
5589 pRoamProfile->ChannelInfo.ChannelList =
5590 &pHddStaCtx->conn_info.operationChannel;
5591 }
5592 else
5593 {
5594 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5595 __func__, channelNum);
5596 return -EINVAL;
5597 }
5598 }
5599
5600 /* Initialize security parameters */
5601 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5602 if (status < 0)
5603 {
5604 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5605 __func__);
5606 return status;
5607 }
5608
5609 /* Issue connect start */
5610 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005611 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005612
5613 if (0 > status)
5614 {
5615 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5616 return status;
5617 }
5618
5619 return 0;
5620}
5621
5622/*
5623 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5624 * This function is used to leave an IBSS
5625 */
5626static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5627 struct net_device *dev
5628 )
5629{
5630 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5631 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5632 tCsrRoamProfile *pRoamProfile;
5633
5634 ENTER();
5635
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005636 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5637 {
5638 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5639 "%s:LOGP in Progress. Ignore!!!", __func__);
5640 return -EAGAIN;
5641 }
5642
Jeff Johnson295189b2012-06-20 16:38:30 -07005643 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5644 if (NULL == pWextState)
5645 {
5646 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5647 __func__);
5648 return -EIO;
5649 }
5650
5651 pRoamProfile = &pWextState->roamProfile;
5652
5653 /* Issue disconnect only if interface type is set to IBSS */
5654 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5655 {
5656 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5657 __func__);
5658 return -EINVAL;
5659 }
5660
5661 /* Issue Disconnect request */
5662 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5663 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5664 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5665
5666 return 0;
5667}
5668
5669/*
5670 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5671 * This function is used to set the phy parameters
5672 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5673 */
5674static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5675 u32 changed)
5676{
5677 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5678 tHalHandle hHal = pHddCtx->hHal;
5679
5680 ENTER();
5681
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005682 if ( pHddCtx->isLogpInProgress )
5683 {
5684 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5685 "%s:LOGP in Progress. Ignore!!!", __func__);
5686 return -EAGAIN;
5687 }
5688
Jeff Johnson295189b2012-06-20 16:38:30 -07005689 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
5690 {
5691 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
5692 WNI_CFG_RTS_THRESHOLD_STAMAX :
5693 wiphy->rts_threshold;
5694
5695 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
5696 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
5697 {
5698 hddLog(VOS_TRACE_LEVEL_ERROR,
5699 "%s: Invalid RTS Threshold value %hu",
5700 __func__, rts_threshold);
5701 return -EINVAL;
5702 }
5703
5704 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
5705 rts_threshold, ccmCfgSetCallback,
5706 eANI_BOOLEAN_TRUE))
5707 {
5708 hddLog(VOS_TRACE_LEVEL_ERROR,
5709 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
5710 __func__, rts_threshold);
5711 return -EIO;
5712 }
5713
5714 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
5715 rts_threshold);
5716 }
5717
5718 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
5719 {
5720 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
5721 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
5722 wiphy->frag_threshold;
5723
5724 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
5725 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
5726 {
5727 hddLog(VOS_TRACE_LEVEL_ERROR,
5728 "%s: Invalid frag_threshold value %hu", __func__,
5729 frag_threshold);
5730 return -EINVAL;
5731 }
5732
5733 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
5734 frag_threshold, ccmCfgSetCallback,
5735 eANI_BOOLEAN_TRUE))
5736 {
5737 hddLog(VOS_TRACE_LEVEL_ERROR,
5738 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
5739 __func__, frag_threshold);
5740 return -EIO;
5741 }
5742
5743 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
5744 frag_threshold);
5745 }
5746
5747 if ((changed & WIPHY_PARAM_RETRY_SHORT)
5748 || (changed & WIPHY_PARAM_RETRY_LONG))
5749 {
5750 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
5751 wiphy->retry_short :
5752 wiphy->retry_long;
5753
5754 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
5755 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
5756 {
5757 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
5758 __func__, retry_value);
5759 return -EINVAL;
5760 }
5761
5762 if (changed & WIPHY_PARAM_RETRY_SHORT)
5763 {
5764 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
5765 retry_value, ccmCfgSetCallback,
5766 eANI_BOOLEAN_TRUE))
5767 {
5768 hddLog(VOS_TRACE_LEVEL_ERROR,
5769 "%s: ccmCfgSetInt failed for long retry count %hu",
5770 __func__, retry_value);
5771 return -EIO;
5772 }
5773 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
5774 __func__, retry_value);
5775 }
5776 else if (changed & WIPHY_PARAM_RETRY_SHORT)
5777 {
5778 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
5779 retry_value, ccmCfgSetCallback,
5780 eANI_BOOLEAN_TRUE))
5781 {
5782 hddLog(VOS_TRACE_LEVEL_ERROR,
5783 "%s: ccmCfgSetInt failed for short retry count %hu",
5784 __func__, retry_value);
5785 return -EIO;
5786 }
5787 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
5788 __func__, retry_value);
5789 }
5790 }
5791
5792 return 0;
5793}
5794
5795/*
5796 * FUNCTION: wlan_hdd_cfg80211_set_txpower
5797 * This function is used to set the txpower
5798 */
5799static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
5800#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
5801 enum tx_power_setting type,
5802#else
5803 enum nl80211_tx_power_setting type,
5804#endif
5805 int dbm)
5806{
5807 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5808 tHalHandle hHal = pHddCtx->hHal;
5809 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5810 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5811
5812 ENTER();
5813
5814 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
5815 dbm, ccmCfgSetCallback,
5816 eANI_BOOLEAN_TRUE))
5817 {
5818 hddLog(VOS_TRACE_LEVEL_ERROR,
5819 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
5820 return -EIO;
5821 }
5822
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005823 if ( pHddCtx->isLogpInProgress )
5824 {
5825 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5826 "%s:LOGP in Progress. Ignore!!!", __func__);
5827 return -EAGAIN;
5828 }
5829
Jeff Johnson295189b2012-06-20 16:38:30 -07005830 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
5831 dbm);
5832
5833 switch(type)
5834 {
5835 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
5836 /* Fall through */
5837 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
5838 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
5839 {
5840 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
5841 __func__);
5842 return -EIO;
5843 }
5844 break;
5845 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
5846 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
5847 __func__);
5848 return -EOPNOTSUPP;
5849 break;
5850 default:
5851 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
5852 __func__, type);
5853 return -EIO;
5854 }
5855
5856 return 0;
5857}
5858
5859/*
5860 * FUNCTION: wlan_hdd_cfg80211_get_txpower
5861 * This function is used to read the txpower
5862 */
5863static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
5864{
5865
5866 hdd_adapter_t *pAdapter;
5867 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5868
Jeff Johnsone7245742012-09-05 17:12:55 -07005869 ENTER();
5870
Jeff Johnson295189b2012-06-20 16:38:30 -07005871 if (NULL == pHddCtx)
5872 {
5873 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
5874 *dbm = 0;
5875 return -ENOENT;
5876 }
5877
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005878 if ( pHddCtx->isLogpInProgress )
5879 {
5880 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5881 "%s:LOGP in Progress. Ignore!!!", __func__);
5882 return -EAGAIN;
5883 }
5884
Jeff Johnson295189b2012-06-20 16:38:30 -07005885 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5886 if (NULL == pAdapter)
5887 {
5888 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
5889 return -ENOENT;
5890 }
5891
5892 wlan_hdd_get_classAstats(pAdapter);
5893 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
5894
Jeff Johnsone7245742012-09-05 17:12:55 -07005895 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005896 return 0;
5897}
5898
5899static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
5900 u8* mac, struct station_info *sinfo)
5901{
5902 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5903 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5904 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
5905 tANI_U8 rate_flags;
5906
5907 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5908 hdd_config_t *pCfg = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07005909
5910 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
5911 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
5912 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
5913 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
5914 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
5915 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
5916 tANI_U16 maxRate = 0;
5917 tANI_U16 myRate;
5918 tANI_U16 currentRate = 0;
5919 tANI_U8 maxSpeedMCS = 0;
5920 tANI_U8 maxMCSIdx = 0;
5921 tANI_U8 rateFlag = 1;
5922 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005923 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07005924
Jeff Johnsone7245742012-09-05 17:12:55 -07005925 ENTER();
5926
Jeff Johnson295189b2012-06-20 16:38:30 -07005927 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
5928 (0 == ssidlen))
5929 {
5930 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
5931 " Invalid ssidlen, %d", __func__, ssidlen);
5932 /*To keep GUI happy*/
5933 return 0;
5934 }
5935
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005936 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5937 {
5938 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5939 "%s:LOGP in Progress. Ignore!!!", __func__);
5940 return -EAGAIN;
5941 }
5942
Jeff Johnson295189b2012-06-20 16:38:30 -07005943 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
5944 sinfo->filled |= STATION_INFO_SIGNAL;
5945
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005946 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005947 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
5948
5949 //convert to the UI units of 100kbps
5950 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
5951
5952#ifdef LINKSPEED_DEBUG_ENABLED
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005953 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 -07005954 sinfo->signal,
5955 pCfg->reportMaxLinkSpeed,
5956 myRate,
5957 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005958 (int) pCfg->linkSpeedRssiMid,
5959 (int) pCfg->linkSpeedRssiLow,
5960 (int) rate_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005961#endif //LINKSPEED_DEBUG_ENABLED
5962
5963 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
5964 {
5965 // we do not want to necessarily report the current speed
5966 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
5967 {
5968 // report the max possible speed
5969 rssidx = 0;
5970 }
5971 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
5972 {
5973 // report the max possible speed with RSSI scaling
5974 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
5975 {
5976 // report the max possible speed
5977 rssidx = 0;
5978 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005979 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07005980 {
5981 // report middle speed
5982 rssidx = 1;
5983 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005984 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
5985 {
5986 // report middle speed
5987 rssidx = 2;
5988 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005989 else
5990 {
5991 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005992 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07005993 }
5994 }
5995 else
5996 {
5997 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
5998 hddLog(VOS_TRACE_LEVEL_ERROR,
5999 "%s: Invalid value for reportMaxLinkSpeed: %u",
6000 __func__, pCfg->reportMaxLinkSpeed);
6001 rssidx = 0;
6002 }
6003
6004 maxRate = 0;
6005
6006 /* Get Basic Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306007 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_OPERATIONAL_RATE_SET,
6008 OperationalRates, &ORLeng))
6009 {
6010 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6011 /*To keep GUI happy*/
6012 return 0;
6013 }
6014
Jeff Johnson295189b2012-06-20 16:38:30 -07006015 for (i = 0; i < ORLeng; i++)
6016 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006017 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006018 {
6019 /* Validate Rate Set */
6020 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
6021 {
6022 currentRate = supported_data_rate[j].supported_rate[rssidx];
6023 break;
6024 }
6025 }
6026 /* Update MAX rate */
6027 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6028 }
6029
6030 /* Get Extended Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306031 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
6032 ExtendedRates, &ERLeng))
6033 {
6034 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6035 /*To keep GUI happy*/
6036 return 0;
6037 }
6038
Jeff Johnson295189b2012-06-20 16:38:30 -07006039 for (i = 0; i < ERLeng; i++)
6040 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006041 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006042 {
6043 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
6044 {
6045 currentRate = supported_data_rate[j].supported_rate[rssidx];
6046 break;
6047 }
6048 }
6049 /* Update MAX rate */
6050 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6051 }
6052
6053 /* Get MCS Rate Set -- but only if we are connected at MCS
6054 rates or if we are always reporting max speed or if we have
6055 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006056 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07006057 {
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306058 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_CURRENT_MCS_SET,
6059 MCSRates, &MCSLeng))
6060 {
6061 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6062 /*To keep GUI happy*/
6063 return 0;
6064 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006065 rateFlag = 0;
6066 if (rate_flags & eHAL_TX_RATE_HT40)
6067 {
6068 rateFlag |= 1;
6069 }
6070 if (rate_flags & eHAL_TX_RATE_SGI)
6071 {
6072 rateFlag |= 2;
6073 }
6074
6075 for (i = 0; i < MCSLeng; i++)
6076 {
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006077 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
6078 for (j = 0; j < temp; j++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006079 {
6080 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
6081 {
6082 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
6083 break;
6084 }
6085 }
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006086 if ((j < temp) && (currentRate > maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006087 {
6088 maxRate = currentRate;
6089 maxSpeedMCS = 1;
6090 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
6091 }
6092 }
6093 }
6094
6095 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006096 if (((maxRate < myRate) && (0 == rssidx)) ||
6097 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006098 {
6099 maxRate = myRate;
6100 if (rate_flags & eHAL_TX_RATE_LEGACY)
6101 {
6102 maxSpeedMCS = 0;
6103 }
6104 else
6105 {
6106 maxSpeedMCS = 1;
6107 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6108 }
6109 }
6110
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006111 if ((!maxSpeedMCS) || (0 != rssidx))
Jeff Johnson295189b2012-06-20 16:38:30 -07006112 {
6113 sinfo->txrate.legacy = maxRate;
6114#ifdef LINKSPEED_DEBUG_ENABLED
6115 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
6116#endif //LINKSPEED_DEBUG_ENABLED
6117 }
6118 else
6119 {
6120 sinfo->txrate.mcs = maxMCSIdx;
6121 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6122 if (rate_flags & eHAL_TX_RATE_SGI)
6123 {
6124 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6125 }
6126 if (rate_flags & eHAL_TX_RATE_HT40)
6127 {
6128 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6129 }
6130#ifdef LINKSPEED_DEBUG_ENABLED
6131 pr_info("Reporting MCS rate %d flags %x\n",
6132 sinfo->txrate.mcs,
6133 sinfo->txrate.flags );
6134#endif //LINKSPEED_DEBUG_ENABLED
6135 }
6136 }
6137 else
6138 {
6139 // report current rate instead of max rate
6140
6141 if (rate_flags & eHAL_TX_RATE_LEGACY)
6142 {
6143 //provide to the UI in units of 100kbps
6144 sinfo->txrate.legacy = myRate;
6145#ifdef LINKSPEED_DEBUG_ENABLED
6146 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
6147#endif //LINKSPEED_DEBUG_ENABLED
6148 }
6149 else
6150 {
6151 //must be MCS
6152 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6153 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6154 if (rate_flags & eHAL_TX_RATE_SGI)
6155 {
6156 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6157 }
6158 if (rate_flags & eHAL_TX_RATE_HT40)
6159 {
6160 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6161 }
6162#ifdef LINKSPEED_DEBUG_ENABLED
6163 pr_info("Reporting actual MCS rate %d flags %x\n",
6164 sinfo->txrate.mcs,
6165 sinfo->txrate.flags );
6166#endif //LINKSPEED_DEBUG_ENABLED
6167 }
6168 }
6169 sinfo->filled |= STATION_INFO_TX_BITRATE;
6170
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006171 sinfo->tx_packets =
6172 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
6173 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
6174 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
6175 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
6176
6177 sinfo->tx_retries =
6178 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
6179 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
6180 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
6181 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
6182
6183 sinfo->tx_failed =
6184 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
6185 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
6186 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
6187 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
6188
6189 sinfo->filled |=
6190 STATION_INFO_TX_PACKETS |
6191 STATION_INFO_TX_RETRIES |
6192 STATION_INFO_TX_FAILED;
6193
6194 EXIT();
6195 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006196}
6197
6198static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
6199 struct net_device *dev, bool mode, v_SINT_t timeout)
6200{
6201 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6202 VOS_STATUS vos_status;
6203
Jeff Johnsone7245742012-09-05 17:12:55 -07006204 ENTER();
6205
Jeff Johnson295189b2012-06-20 16:38:30 -07006206 if (NULL == pAdapter)
6207 {
6208 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6209 return -ENODEV;
6210 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006211 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6212 {
6213 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6214 "%s:LOGP in Progress. Ignore!!!", __func__);
6215 return -EAGAIN;
6216 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006217
6218 /**The get power cmd from the supplicant gets updated by the nl only
6219 *on successful execution of the function call
6220 *we are oppositely mapped w.r.t mode in the driver
6221 **/
6222 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
6223
Jeff Johnsone7245742012-09-05 17:12:55 -07006224 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006225 if (VOS_STATUS_E_FAILURE == vos_status)
6226 {
6227 return -EINVAL;
6228 }
6229 return 0;
6230}
6231
6232
6233#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6234static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
6235 struct net_device *netdev,
6236 u8 key_index)
6237{
Jeff Johnsone7245742012-09-05 17:12:55 -07006238 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006239 return 0;
6240}
6241#endif //LINUX_VERSION_CODE
6242
6243#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
6244static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6245 struct net_device *dev,
6246 struct ieee80211_txq_params *params)
6247{
Jeff Johnsone7245742012-09-05 17:12:55 -07006248 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006249 return 0;
6250}
6251#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6252static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6253 struct ieee80211_txq_params *params)
6254{
Jeff Johnsone7245742012-09-05 17:12:55 -07006255 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006256 return 0;
6257}
6258#endif //LINUX_VERSION_CODE
6259
6260static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
6261 struct net_device *dev, u8 *mac)
6262{
6263 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006264 VOS_STATUS vos_status;
6265 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006266
Jeff Johnsone7245742012-09-05 17:12:55 -07006267 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006268 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6269 {
6270 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6271 return -EINVAL;
6272 }
6273
6274 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6275 {
6276 hddLog( LOGE,
6277 "%s: Wlan Load/Unload is in progress", __func__);
6278 return -EBUSY;
6279 }
6280
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006281 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6282 {
6283 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6284 "%s:LOGP in Progress. Ignore!!!", __func__);
6285 return -EAGAIN;
6286 }
6287
Jeff Johnson295189b2012-06-20 16:38:30 -07006288 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
6289#ifdef WLAN_FEATURE_P2P
6290 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
6291#endif
6292 )
6293 {
6294 if( NULL == mac )
6295 {
6296 v_U16_t i;
6297 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
6298 {
6299 if(pAdapter->aStaInfo[i].isUsed)
6300 {
6301 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
6302 hddLog(VOS_TRACE_LEVEL_INFO,
6303 "%s: Delete STA with MAC::"
6304 "%02x:%02x:%02x:%02x:%02x:%02x",
6305 __func__,
6306 macAddr[0], macAddr[1], macAddr[2],
6307 macAddr[3], macAddr[4], macAddr[5]);
6308 hdd_softap_sta_deauth(pAdapter, macAddr);
6309 }
6310 }
6311 }
6312 else
6313 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006314
6315 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
6316 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6317 {
6318 hddLog(VOS_TRACE_LEVEL_INFO,
6319 "%s: Skip this DEL STA as this is not used::"
6320 "%02x:%02x:%02x:%02x:%02x:%02x",
6321 __func__,
6322 mac[0], mac[1], mac[2],
6323 mac[3], mac[4], mac[5]);
6324 return -ENOENT;
6325 }
6326
6327 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
6328 {
6329 hddLog(VOS_TRACE_LEVEL_INFO,
6330 "%s: Skip this DEL STA as deauth is in progress::"
6331 "%02x:%02x:%02x:%02x:%02x:%02x",
6332 __func__,
6333 mac[0], mac[1], mac[2],
6334 mac[3], mac[4], mac[5]);
6335 return -ENOENT;
6336 }
6337
6338 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
6339
Jeff Johnson295189b2012-06-20 16:38:30 -07006340 hddLog(VOS_TRACE_LEVEL_INFO,
6341 "%s: Delete STA with MAC::"
6342 "%02x:%02x:%02x:%02x:%02x:%02x",
6343 __func__,
6344 mac[0], mac[1], mac[2],
6345 mac[3], mac[4], mac[5]);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006346
6347 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
6348 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6349 {
6350 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
6351 hddLog(VOS_TRACE_LEVEL_INFO,
6352 "%s: STA removal failed for ::"
6353 "%02x:%02x:%02x:%02x:%02x:%02x",
6354 __func__,
6355 mac[0], mac[1], mac[2],
6356 mac[3], mac[4], mac[5]);
6357 return -ENOENT;
6358 }
6359
Jeff Johnson295189b2012-06-20 16:38:30 -07006360 }
6361 }
6362
6363 EXIT();
6364
6365 return 0;
6366}
6367
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006368#ifdef FEATURE_WLAN_TDLS
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006369static int wlan_hdd_tdls_add_station(struct wiphy *wiphy,
6370 struct net_device *dev, u8 *mac)
6371{
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006372 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6373 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006374 VOS_STATUS status;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006375
Jeff Johnsone7245742012-09-05 17:12:55 -07006376 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006377
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006378 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006379 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006380 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006381 "Invalid arguments");
6382 return -EINVAL;
6383 }
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006384 if (pHddCtx->isLogpInProgress)
6385 {
6386 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6387 "%s:LOGP in Progress. Ignore!!!", __func__);
6388 return -EBUSY;
6389 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006390
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006391 if (FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006392 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006393 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006394 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006395 "TDLS Disabled in INI OR not enabled in FW.\
6396 Cannot process TDLS commands \n");
6397 return -ENOTSUPP;
6398 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006399
6400 if (wlan_hdd_tdls_is_progress(mac, TRUE))
6401 {
6402 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6403 "%s: TDLS setup is ongoing. Request declined.",__func__);
6404 return -EPERM;
6405 }
6406
Lee Hoonkic1262f22013-01-24 21:59:00 -08006407 /* first to check if we reached to maximum supported TDLS peer.
6408 TODO: for now, return -EPERM looks working fine,
6409 but need to check if any other errno fit into this category.*/
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006410 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers())
Lee Hoonkic1262f22013-01-24 21:59:00 -08006411 {
6412 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6413 "%s: TDLS Max peer already connected. Request declined. \n",
6414 __func__);
6415 return -EPERM;
6416 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006417 else
6418 {
6419 hddTdlsPeer_t *pTdlsPeer;
6420 pTdlsPeer = wlan_hdd_tdls_find_peer(mac);
6421 if (pTdlsPeer && (eTDLS_LINK_CONNECTED == pTdlsPeer->link_status))
6422 {
6423 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6424 "%s: %02x:%02x:%02x:%02x:%02x:%02x already connected. Request declined.",
6425 __func__, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
6426 return -EPERM;
6427 }
6428 }
6429
6430 wlan_hdd_tdls_set_connection_progress(mac,TRUE);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006431
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006432 INIT_COMPLETION(pAdapter->tdls_add_station_comp);
6433
6434 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
6435 pAdapter->sessionId, mac);
6436
6437 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_add_station_comp,
6438 msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
6439
6440 if (!status)
6441 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006442 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006443 "%s: timeout waiting for tdls add station indication",
6444 __func__);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006445 wlan_hdd_tdls_set_connection_progress(mac, FALSE);
6446 return -EPERM;
6447 }
6448 if ( eHAL_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus)
6449 {
6450 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6451 "%s: Add Station is unsucessful", __func__);
6452 wlan_hdd_tdls_set_connection_progress(mac, FALSE);
6453 return -EPERM;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006454 }
6455
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006456 return 0;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006457}
6458#endif
6459
6460static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
6461 struct net_device *dev, u8 *mac, struct station_parameters *params)
6462{
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006463 int status = -EPERM;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006464#ifdef FEATURE_WLAN_TDLS
6465 u32 mask, set;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006466 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006467 mask = params->sta_flags_mask;
6468
6469 set = params->sta_flags_set;
6470
Lee Hoonkic1262f22013-01-24 21:59:00 -08006471 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6472 "%s: mask 0x%x set 0x%x\n",__func__, mask, set);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006473
6474 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6475 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006476 status = wlan_hdd_tdls_add_station(wiphy, dev, mac);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006477 }
6478 }
6479#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006480 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006481}
6482
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006483
6484#ifdef FEATURE_WLAN_LFR
6485static int wlan_hdd_cfg80211_set_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{
6488#define MAX_PMKSAIDS_IN_CACHE 8
6489 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -07006490 static tANI_U32 i; // HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006491 tANI_U32 j=0;
6492 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6493 tHalHandle halHandle;
6494 eHalStatus result;
6495 tANI_U8 BSSIDMatched = 0;
6496
Jeff Johnsone7245742012-09-05 17:12:55 -07006497 ENTER();
6498
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006499 // Validate pAdapter
6500 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6501 {
6502 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6503 return -EINVAL;
6504 }
6505
6506 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6507 {
6508 hddLog( LOGE,
6509 "%s: Wlan Load/Unload is in progress", __func__);
6510 return -EBUSY;
6511 }
6512
6513 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6514 {
6515 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6516 "%s:LOGP in Progress. Ignore!!!", __func__);
6517 return -EAGAIN;
6518 }
6519
6520 // Retrieve halHandle
6521 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
6522
6523 for (j = 0; j < i; j++)
6524 {
6525 if(vos_mem_compare(PMKIDCache[j].BSSID,
6526 pmksa->bssid, WNI_CFG_BSSID_LEN))
6527 {
6528 /* BSSID matched previous entry. Overwrite it. */
6529 BSSIDMatched = 1;
6530 vos_mem_copy(PMKIDCache[j].BSSID,
6531 pmksa->bssid, WNI_CFG_BSSID_LEN);
6532 vos_mem_copy(PMKIDCache[j].PMKID,
6533 pmksa->pmkid,
6534 CSR_RSN_PMKID_SIZE);
6535 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006536 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006537 dump_bssid(pmksa->bssid);
6538 dump_pmkid(halHandle, pmksa->pmkid);
6539 break;
6540 }
6541 }
6542
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07006543 /* Check we compared all entries,if then take the first slot now */
6544 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
6545
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006546 if (!BSSIDMatched)
6547 {
6548 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
6549 vos_mem_copy(PMKIDCache[i].BSSID,
6550 pmksa->bssid, ETHER_ADDR_LEN);
6551 vos_mem_copy(PMKIDCache[i].PMKID,
6552 pmksa->pmkid,
6553 CSR_RSN_PMKID_SIZE);
6554 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006555 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006556 dump_bssid(pmksa->bssid);
6557 dump_pmkid(halHandle, pmksa->pmkid);
6558 // Increment the HDD Local Cache index
6559 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
6560 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
6561 }
6562
6563
6564 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
6565 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006566 // __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006567 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006568 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006569 // Finally set the PMKSA ID Cache in CSR
6570 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
6571 PMKIDCache,
6572 i );
6573 return 0;
6574}
6575
6576
6577static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006578 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006579{
Jeff Johnsone7245742012-09-05 17:12:55 -07006580 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006581 // TODO: Implement this later.
6582 return 0;
6583}
6584
6585static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
6586{
Jeff Johnsone7245742012-09-05 17:12:55 -07006587 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006588 // TODO: Implement this later.
6589 return 0;
6590}
6591#endif
6592
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006593#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6594static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
6595 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
6596{
6597 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6598 hdd_station_ctx_t *pHddStaCtx;
6599
6600 if (NULL == pAdapter)
6601 {
6602 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6603 return -ENODEV;
6604 }
6605
6606 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6607
6608 // Added for debug on reception of Re-assoc Req.
6609 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6610 {
6611 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
6612 ftie->ie_len);
6613 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
6614 }
6615
6616#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
6617 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
6618 ftie->ie_len);
6619#endif
6620
6621 // Pass the received FT IEs to SME
6622 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, ftie->ie,
6623 ftie->ie_len);
6624 return 0;
6625}
6626#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006627
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006628#ifdef FEATURE_WLAN_TDLS
6629static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
6630 u8 *peer, u8 action_code, u8 dialog_token,
6631 u16 status_code, const u8 *buf, size_t len)
6632{
6633
6634 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6635 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006636 u8 peerMac[6];
6637 VOS_STATUS status;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006638 int ret = 0;
Hoonki Leea34dd892013-02-05 22:56:02 -08006639 int responder;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006640
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006641 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006642 {
6643 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6644 "Invalid arguments");
6645 return -EINVAL;
6646 }
6647
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006648 if (pHddCtx->isLogpInProgress)
6649 {
6650 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6651 "%s:LOGP in Progress. Ignore!!!", __func__);
6652 return -EBUSY;
6653 }
6654
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006655 if (FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006656 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6657 {
6658 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6659 "TDLS Disabled in INI OR not enabled in FW.\
6660 Cannot process TDLS commands \n");
6661 return -ENOTSUPP;
6662 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006663
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006664 if (WLAN_IS_TDLS_SETUP_ACTION(action_code))
6665 {
6666 if (wlan_hdd_tdls_is_progress(peer, TRUE))
6667 {
6668 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6669 "%s: TDLS setup is ongoing. Request declined.", __func__);
6670 return -EPERM;
6671 }
6672 }
6673
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006674 if (SIR_MAC_TDLS_SETUP_REQ == action_code ||
6675 SIR_MAC_TDLS_SETUP_RSP == action_code )
Lee Hoonkic1262f22013-01-24 21:59:00 -08006676 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006677 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers())
Lee Hoonkic1262f22013-01-24 21:59:00 -08006678 {
6679 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
6680 we return error code at 'add_station()'. Hence we have this
6681 check again in addtion to add_station().
6682 Anyway, there is no hard to double-check. */
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006683 if (SIR_MAC_TDLS_SETUP_REQ == action_code)
Lee Hoonkic1262f22013-01-24 21:59:00 -08006684 {
6685 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6686 "%s: TDLS Max peer already connected. Request declined. \n",
6687 __func__);
6688 return -EPERM;
6689 }
6690 else
6691 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006692 /* maximum reached. tweak to send error code to peer and return
6693 error code to supplicant */
Lee Hoonkic1262f22013-01-24 21:59:00 -08006694 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
6695 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6696 "%s: TDLS Max peer already connected send response status %d \n",
6697 __func__,status_code);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006698 ret = -EPERM;
6699 /* fall through to send setup resp with failure status
6700 code */
Lee Hoonkic1262f22013-01-24 21:59:00 -08006701 }
6702 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006703 else
6704 {
6705 hddTdlsPeer_t *pTdlsPeer;
6706 pTdlsPeer = wlan_hdd_tdls_find_peer(peer);
6707 if (pTdlsPeer && (eTDLS_LINK_CONNECTED == pTdlsPeer->link_status))
6708 {
6709 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6710 "%s: %02x:%02x:%02x:%02x:%02x:%02x already connected. Request declined.",
6711 __func__, peer[0], peer[1], peer[2], peer[3], peer[4], peer[5]);
6712 return -EPERM;
6713 }
6714 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006715 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006716 vos_mem_copy(peerMac, peer, 6);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006717
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006718#ifdef WLAN_FEATURE_TDLS_DEBUG
6719 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6720 "%s: %02x:%02x:%02x:%02x:%02x:%02x) action %d, dialog_token %d status %d, len = %d",
6721 "tdls_mgmt", peer[0], peer[1], peer[2], peer[3], peer[4], peer[5],
6722 action_code, dialog_token, status_code, len);
6723#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006724
Hoonki Leea34dd892013-02-05 22:56:02 -08006725 /*Except teardown responder will not be used so just make 0*/
6726 responder = 0;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006727 if (SIR_MAC_TDLS_TEARDOWN == action_code)
Hoonki Leea34dd892013-02-05 22:56:02 -08006728 {
6729 responder = wlan_hdd_tdls_get_responder(peerMac);
6730 if(-1 == responder)
6731 {
6732 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6733 "%s: %02x:%02x:%02x:%02x:%02x:%02x) peer doesn't exist dialog_token %d status %d, len = %d",
6734 "tdls_mgmt", peer[0], peer[1], peer[2], peer[3], peer[4], peer[5],
6735 dialog_token, status_code, len);
6736 return -EPERM;
6737 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006738 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006739
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006740 if(ret == 0 && /* if failure, don't need to set the progress bit */
6741 (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
6742 wlan_hdd_tdls_set_connection_progress(peer, TRUE);
6743
6744 INIT_COMPLETION(pAdapter->tdls_mgmt_comp);
6745
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006746 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
Hoonki Leea34dd892013-02-05 22:56:02 -08006747 peerMac, action_code, dialog_token, status_code, (tANI_U8 *)buf, len, responder);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006748
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006749 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_add_station_comp,
6750 msecs_to_jiffies(WAIT_TIME_TDLS_MGMT));
6751
6752 if (VOS_STATUS_SUCCESS != status)
6753 {
6754 if(ret == 0 && /* if failure, don't need to set the progress bit */
6755 (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
6756 wlan_hdd_tdls_set_connection_progress(peer, FALSE);
6757
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006758 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6759 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006760 return -EPERM;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006761 }
6762
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006763 if (TRUE != pAdapter->mgmtTxCompletionStatus)
6764 {
6765 if(ret == 0 && /* if failure, don't need to set the progress bit */
6766 (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
6767 wlan_hdd_tdls_set_connection_progress(peer, FALSE);
6768
6769 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6770 "%s: Mgmt Tx Completion failed!", __func__);
6771 return -EPERM;
6772 }
6773
6774 if (ret)
6775 return ret;
6776
Hoonki Leea34dd892013-02-05 22:56:02 -08006777 if (SIR_MAC_TDLS_SETUP_RSP == action_code)
6778 {
6779 wlan_hdd_tdls_set_responder(peerMac, TRUE);
6780 }
6781 else if (SIR_MAC_TDLS_SETUP_CNF == action_code)
6782 {
6783 wlan_hdd_tdls_set_responder(peerMac, FALSE);
6784 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006785
6786 return 0;
6787}
6788
6789static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
6790 u8 *peer, enum nl80211_tdls_operation oper)
6791{
6792 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6793 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006794#ifdef WLAN_FEATURE_TDLS_DEBUG
6795 const char *tdls_oper_str[]= {
6796 "NL80211_TDLS_DISCOVERY_REQ",
6797 "NL80211_TDLS_SETUP",
6798 "NL80211_TDLS_TEARDOWN",
6799 "NL80211_TDLS_ENABLE_LINK",
6800 "NL80211_TDLS_DISABLE_LINK",
6801 "NL80211_TDLS_UNKONW_OPER"};
6802#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006803
6804 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6805 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006806 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006807 "Invalid arguments");
6808 return -EINVAL;
6809 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006810
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006811 if (pHddCtx->isLogpInProgress)
6812 {
6813 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6814 "%s:LOGP in Progress. Ignore!!!", __func__);
6815 return -EBUSY;
6816 }
6817
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006818#ifdef WLAN_FEATURE_TDLS_DEBUG
6819 if((int)oper > 4)
6820 oper = 5;
6821
6822 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6823 "%s: %02x:%02x:%02x:%02x:%02x:%02x: %d (%s) ", "tdls_oper",
6824 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5], (int)oper,
6825 tdls_oper_str[(int)oper]);
6826#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006827
6828 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006829 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006830 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006831 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006832 "TDLS Disabled in INI OR not enabled in FW.\
6833 Cannot process TDLS commands \n");
6834 return -ENOTSUPP;
6835 }
6836
6837 switch (oper) {
6838 case NL80211_TDLS_ENABLE_LINK:
6839 {
Hoonki Lee387663d2013-02-05 18:08:43 -08006840 hddTdlsPeer_t *pTdlsPeer;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006841 VOS_STATUS status;
6842
6843 if (peer) {
Hoonki Lee387663d2013-02-05 18:08:43 -08006844 pTdlsPeer = wlan_hdd_tdls_find_peer(peer);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006845
6846 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
Hoonki Lee387663d2013-02-05 18:08:43 -08006847 "%s: TDLS_LINK_ENABLE %2x:%2x:%2x:%2x:%2x:%2x",
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006848 __func__, peer[0], peer[1],
6849 peer[2], peer[3],
6850 peer[4], peer[5] );
6851
Hoonki Lee387663d2013-02-05 18:08:43 -08006852 if ( NULL == pTdlsPeer ) {
6853 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_hdd_tdls_find_peer %2x:%2x:%2x:%2x:%2x:%2x failed",
6854 __func__, peer[0], peer[1],
6855 peer[2], peer[3],
6856 peer[4], peer[5] );
Hoonki Leef63df0d2013-01-16 19:29:14 -08006857 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006858 }
6859
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006860 if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status)
6861 {
6862 /* start TDLS client registration with TL */
6863 status = hdd_roamRegisterTDLSSTA( pAdapter, peer, pTdlsPeer->staId, pTdlsPeer->signature);
6864 wlan_hdd_tdls_increment_peer_count();
6865 wlan_hdd_tdls_set_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
6866 wlan_hdd_tdls_check_bmps(pHddCtx);
6867 wlan_hdd_tdls_set_connection_progress(peer, FALSE);
6868 }
Chilam NG571c65a2013-01-19 12:27:36 +05306869
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006870 } else {
6871 hddLog(VOS_TRACE_LEVEL_WARN, "wlan_hdd_cfg80211_add_key: peer NULL" );
6872 }
6873 }
6874 break;
6875 case NL80211_TDLS_DISABLE_LINK:
Lee Hoonkic1262f22013-01-24 21:59:00 -08006876 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006877 hddTdlsPeer_t *curr_peer = wlan_hdd_tdls_find_peer(peer);
6878
6879 if(NULL != curr_peer)
Lee Hoonkic1262f22013-01-24 21:59:00 -08006880 {
6881 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
6882 pAdapter->sessionId, peer );
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006883 curr_peer->isTDLSInProgress = FALSE;
Lee Hoonkic1262f22013-01-24 21:59:00 -08006884 }
6885 else
6886 {
6887 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6888 "%s: TDLS Peer Station doesn't exist \n",__func__);
6889 }
6890 return 0;
6891 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006892 case NL80211_TDLS_TEARDOWN:
6893 case NL80211_TDLS_SETUP:
6894 case NL80211_TDLS_DISCOVERY_REQ:
6895 /* We don't support in-driver setup/teardown/discovery */
6896 return -ENOTSUPP;
6897 default:
6898 return -ENOTSUPP;
6899 }
6900 return 0;
6901}
Chilam NG571c65a2013-01-19 12:27:36 +05306902
6903int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
6904 struct net_device *dev, u8 *peer)
6905{
6906 hddLog(VOS_TRACE_LEVEL_INFO, "tdls send discover req: %x %x %x %x %x %x",
6907 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5]);
6908
6909 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
6910 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
6911}
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006912#endif
6913
Jeff Johnson295189b2012-06-20 16:38:30 -07006914/* cfg80211_ops */
6915static struct cfg80211_ops wlan_hdd_cfg80211_ops =
6916{
6917 .add_virtual_intf = wlan_hdd_add_virtual_intf,
6918 .del_virtual_intf = wlan_hdd_del_virtual_intf,
6919 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
6920 .change_station = wlan_hdd_change_station,
6921#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
6922 .add_beacon = wlan_hdd_cfg80211_add_beacon,
6923 .del_beacon = wlan_hdd_cfg80211_del_beacon,
6924 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006925#else
6926 .start_ap = wlan_hdd_cfg80211_start_ap,
6927 .change_beacon = wlan_hdd_cfg80211_change_beacon,
6928 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07006929#endif
6930 .change_bss = wlan_hdd_cfg80211_change_bss,
6931 .add_key = wlan_hdd_cfg80211_add_key,
6932 .get_key = wlan_hdd_cfg80211_get_key,
6933 .del_key = wlan_hdd_cfg80211_del_key,
6934 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08006935#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07006936 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08006937#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006938 .scan = wlan_hdd_cfg80211_scan,
6939 .connect = wlan_hdd_cfg80211_connect,
6940 .disconnect = wlan_hdd_cfg80211_disconnect,
6941 .join_ibss = wlan_hdd_cfg80211_join_ibss,
6942 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
6943 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
6944 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
6945 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
6946#ifdef WLAN_FEATURE_P2P
6947 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
6948 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
6949 .mgmt_tx = wlan_hdd_action,
6950#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6951 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
6952 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
6953 .set_txq_params = wlan_hdd_set_txq_params,
6954#endif
6955#endif
6956 .get_station = wlan_hdd_cfg80211_get_station,
6957 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
6958 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006959 .add_station = wlan_hdd_cfg80211_add_station,
6960#ifdef FEATURE_WLAN_LFR
6961 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
6962 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
6963 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
6964#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006965#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6966 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
6967#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006968#ifdef FEATURE_WLAN_TDLS
6969 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
6970 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
6971#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006972};
6973
6974#endif // CONFIG_CFG80211