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