blob: a238c008475b48798f5ecc2449e1e9b232bf3214 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Jeff Johnson32d95a32012-09-10 13:15:23 -07002 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -07003 *
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
22/**========================================================================
23
24 \file wlan_hdd_cfg80211.c
25
26 \brief WLAN Host Device Driver implementation
27
28 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
29
30 Qualcomm Confidential and Proprietary.
31
32 ========================================================================*/
33
34/**=========================================================================
35
36 EDIT HISTORY FOR FILE
37
38
39 This section contains comments describing changes made to the module.
40 Notice that changes are listed in reverse chronological order.
41
42
43 $Header:$ $DateTime: $ $Author: $
44
45
46 when who what, where, why
47 -------- --- --------------------------------------------------------
48 21/12/09 Ashwani Created module.
49
50 07/06/10 Kumar Deepak Implemented cfg80211 callbacks for ANDROID
51 Ganesh K
52 ==========================================================================*/
53
54#ifdef CONFIG_CFG80211
55
56#include <linux/version.h>
57#include <linux/module.h>
58#include <linux/kernel.h>
59#include <linux/init.h>
60#include <linux/wireless.h>
61#include <wlan_hdd_includes.h>
62#include <net/arp.h>
63#include <net/cfg80211.h>
64#include <linux/wireless.h>
65#include <wlan_hdd_wowl.h>
66#include <aniGlobal.h>
67#include "ccmApi.h"
68#include "sirParams.h"
69#include "dot11f.h"
70#include "wlan_hdd_assoc.h"
71#include "wlan_hdd_wext.h"
72#include "sme_Api.h"
73#include "wlan_hdd_p2p.h"
74#include "wlan_hdd_cfg80211.h"
75#include "wlan_hdd_hostapd.h"
76#include "sapInternal.h"
77#include "wlan_hdd_softap_tx_rx.h"
78#include "wlan_hdd_main.h"
79#ifdef WLAN_BTAMP_FEATURE
80#include "bap_hdd_misc.h"
81#endif
82#include <qc_sap_ioctl.h>
83
84#define g_mode_rates_size (12)
85#define a_mode_rates_size (8)
86#define FREQ_BASE_80211G (2407)
87#define FREQ_BAND_DIFF_80211G (5)
Jeff Johnson04dd8a82012-06-29 20:41:40 -070088#define MAX_SCAN_SSID 9
Jeff Johnson295189b2012-06-20 16:38:30 -070089#define GET_IE_LEN_IN_BSS_DESC(lenInBss) ( lenInBss + sizeof(lenInBss) - \
90 ((int) OFFSET_OF( tSirBssDescription, ieFields)))
91
92#define HDD2GHZCHAN(freq, chan, flag) { \
93 .band = IEEE80211_BAND_2GHZ, \
94 .center_freq = (freq), \
95 .hw_value = (chan),\
96 .flags = (flag), \
97 .max_antenna_gain = 0 ,\
98 .max_power = 30, \
99}
100
101#define HDD5GHZCHAN(freq, chan, flag) { \
102 .band = IEEE80211_BAND_5GHZ, \
103 .center_freq = (freq), \
104 .hw_value = (chan),\
105 .flags = (flag), \
106 .max_antenna_gain = 0 ,\
107 .max_power = 30, \
108}
109
110#define HDD_G_MODE_RATETAB(rate, rate_id, flag)\
111{\
112 .bitrate = rate, \
113 .hw_value = rate_id, \
114 .flags = flag, \
115}
116
117static const u32 hdd_cipher_suites[] =
118{
119 WLAN_CIPHER_SUITE_WEP40,
120 WLAN_CIPHER_SUITE_WEP104,
121 WLAN_CIPHER_SUITE_TKIP,
122#ifdef FEATURE_WLAN_CCX
123#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
124 WLAN_CIPHER_SUITE_KRK,
125 WLAN_CIPHER_SUITE_CCMP,
126#else
127 WLAN_CIPHER_SUITE_CCMP,
128#endif
129#ifdef FEATURE_WLAN_WAPI
130 WLAN_CIPHER_SUITE_SMS4,
131#endif
132};
133
134static inline int is_broadcast_ether_addr(const u8 *addr)
135{
136 return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&
137 (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
138}
139
140static struct ieee80211_channel hdd_channels_2_4_GHZ[] =
141{
142 HDD2GHZCHAN(2412, 1, 0) ,
143 HDD2GHZCHAN(2417, 2, 0) ,
144 HDD2GHZCHAN(2422, 3, 0) ,
145 HDD2GHZCHAN(2427, 4, 0) ,
146 HDD2GHZCHAN(2432, 5, 0) ,
147 HDD2GHZCHAN(2437, 6, 0) ,
148 HDD2GHZCHAN(2442, 7, 0) ,
149 HDD2GHZCHAN(2447, 8, 0) ,
150 HDD2GHZCHAN(2452, 9, 0) ,
151 HDD2GHZCHAN(2457, 10, 0) ,
152 HDD2GHZCHAN(2462, 11, 0) ,
153 HDD2GHZCHAN(2467, 12, 0) ,
154 HDD2GHZCHAN(2472, 13, 0) ,
155 HDD2GHZCHAN(2484, 14, 0) ,
156};
157
158#ifdef WLAN_FEATURE_P2P
159static struct ieee80211_channel hdd_social_channels_2_4_GHZ[] =
160{
161 HDD2GHZCHAN(2412, 1, 0) ,
162 HDD2GHZCHAN(2437, 6, 0) ,
163 HDD2GHZCHAN(2462, 11, 0) ,
164};
165#endif
166
167static struct ieee80211_channel hdd_channels_5_GHZ[] =
168{
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700169 HDD5GHZCHAN(4920, 240, 0) ,
170 HDD5GHZCHAN(4940, 244, 0) ,
171 HDD5GHZCHAN(4960, 248, 0) ,
172 HDD5GHZCHAN(4980, 252, 0) ,
173 HDD5GHZCHAN(5040, 208, 0) ,
174 HDD5GHZCHAN(5060, 212, 0) ,
175 HDD5GHZCHAN(5080, 216, 0) ,
Jeff Johnson295189b2012-06-20 16:38:30 -0700176 HDD5GHZCHAN(5180, 36, 0) ,
177 HDD5GHZCHAN(5200, 40, 0) ,
178 HDD5GHZCHAN(5220, 44, 0) ,
179 HDD5GHZCHAN(5240, 48, 0) ,
180 HDD5GHZCHAN(5260, 52, 0) ,
181 HDD5GHZCHAN(5280, 56, 0) ,
182 HDD5GHZCHAN(5300, 60, 0) ,
183 HDD5GHZCHAN(5320, 64, 0) ,
184 HDD5GHZCHAN(5500,100, 0) ,
185 HDD5GHZCHAN(5520,104, 0) ,
186 HDD5GHZCHAN(5540,108, 0) ,
187 HDD5GHZCHAN(5560,112, 0) ,
188 HDD5GHZCHAN(5580,116, 0) ,
189 HDD5GHZCHAN(5600,120, 0) ,
190 HDD5GHZCHAN(5620,124, 0) ,
191 HDD5GHZCHAN(5640,128, 0) ,
192 HDD5GHZCHAN(5660,132, 0) ,
193 HDD5GHZCHAN(5680,136, 0) ,
194 HDD5GHZCHAN(5700,140, 0) ,
195 HDD5GHZCHAN(5745,149, 0) ,
196 HDD5GHZCHAN(5765,153, 0) ,
197 HDD5GHZCHAN(5785,157, 0) ,
198 HDD5GHZCHAN(5805,161, 0) ,
199 HDD5GHZCHAN(5825,165, 0) ,
200};
201
202static struct ieee80211_rate g_mode_rates[] =
203{
204 HDD_G_MODE_RATETAB(10, 0x1, 0),
205 HDD_G_MODE_RATETAB(20, 0x2, 0),
206 HDD_G_MODE_RATETAB(55, 0x4, 0),
207 HDD_G_MODE_RATETAB(110, 0x8, 0),
208 HDD_G_MODE_RATETAB(60, 0x10, 0),
209 HDD_G_MODE_RATETAB(90, 0x20, 0),
210 HDD_G_MODE_RATETAB(120, 0x40, 0),
211 HDD_G_MODE_RATETAB(180, 0x80, 0),
212 HDD_G_MODE_RATETAB(240, 0x100, 0),
213 HDD_G_MODE_RATETAB(360, 0x200, 0),
214 HDD_G_MODE_RATETAB(480, 0x400, 0),
215 HDD_G_MODE_RATETAB(540, 0x800, 0),
216};
217
218static struct ieee80211_rate a_mode_rates[] =
219{
220 HDD_G_MODE_RATETAB(60, 0x10, 0),
221 HDD_G_MODE_RATETAB(90, 0x20, 0),
222 HDD_G_MODE_RATETAB(120, 0x40, 0),
223 HDD_G_MODE_RATETAB(180, 0x80, 0),
224 HDD_G_MODE_RATETAB(240, 0x100, 0),
225 HDD_G_MODE_RATETAB(360, 0x200, 0),
226 HDD_G_MODE_RATETAB(480, 0x400, 0),
227 HDD_G_MODE_RATETAB(540, 0x800, 0),
228};
229
230static struct ieee80211_supported_band wlan_hdd_band_2_4_GHZ =
231{
232 .channels = hdd_channels_2_4_GHZ,
233 .n_channels = ARRAY_SIZE(hdd_channels_2_4_GHZ),
234 .band = IEEE80211_BAND_2GHZ,
235 .bitrates = g_mode_rates,
236 .n_bitrates = g_mode_rates_size,
237 .ht_cap.ht_supported = 1,
238 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
239 | IEEE80211_HT_CAP_GRN_FLD
240 | IEEE80211_HT_CAP_DSSSCCK40
241 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
242 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
243 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
244 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
245 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
246 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
247};
248
249#ifdef WLAN_FEATURE_P2P
250static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_GHZ =
251{
252 .channels = hdd_social_channels_2_4_GHZ,
253 .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_GHZ),
254 .band = IEEE80211_BAND_2GHZ,
255 .bitrates = g_mode_rates,
256 .n_bitrates = g_mode_rates_size,
257 .ht_cap.ht_supported = 1,
258 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
259 | IEEE80211_HT_CAP_GRN_FLD
260 | IEEE80211_HT_CAP_DSSSCCK40
261 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
262 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
263 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
264 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
265 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
266 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
267};
268#endif
269
270static struct ieee80211_supported_band wlan_hdd_band_5_GHZ =
271{
272 .channels = hdd_channels_5_GHZ,
273 .n_channels = ARRAY_SIZE(hdd_channels_5_GHZ),
274 .band = IEEE80211_BAND_5GHZ,
275 .bitrates = a_mode_rates,
276 .n_bitrates = a_mode_rates_size,
277 .ht_cap.ht_supported = 1,
278 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
279 | IEEE80211_HT_CAP_GRN_FLD
280 | IEEE80211_HT_CAP_DSSSCCK40
281 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
282 | IEEE80211_HT_CAP_SGI_40
283 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
284 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
285 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
286 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
287 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
288 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
289};
290
291/* This structure contain information what kind of frame are expected in
292 TX/RX direction for each kind of interface */
293static const struct ieee80211_txrx_stypes
294wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
295 [NL80211_IFTYPE_STATION] = {
296 .tx = 0xffff,
297 .rx = BIT(SIR_MAC_MGMT_ACTION) |
298 BIT(SIR_MAC_MGMT_PROBE_REQ),
299 },
300 [NL80211_IFTYPE_AP] = {
301 .tx = 0xffff,
302 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
303 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
304 BIT(SIR_MAC_MGMT_PROBE_REQ) |
305 BIT(SIR_MAC_MGMT_DISASSOC) |
306 BIT(SIR_MAC_MGMT_AUTH) |
307 BIT(SIR_MAC_MGMT_DEAUTH) |
308 BIT(SIR_MAC_MGMT_ACTION),
309 },
310#ifdef WLAN_FEATURE_P2P
311 [NL80211_IFTYPE_P2P_CLIENT] = {
312 .tx = 0xffff,
313 .rx = BIT(SIR_MAC_MGMT_ACTION) |
314 BIT(SIR_MAC_MGMT_PROBE_REQ),
315 },
316 [NL80211_IFTYPE_P2P_GO] = {
317 /* This is also same as for SoftAP */
318 .tx = 0xffff,
319 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
320 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
321 BIT(SIR_MAC_MGMT_PROBE_REQ) |
322 BIT(SIR_MAC_MGMT_DISASSOC) |
323 BIT(SIR_MAC_MGMT_AUTH) |
324 BIT(SIR_MAC_MGMT_DEAUTH) |
325 BIT(SIR_MAC_MGMT_ACTION),
326 },
327#endif
328};
329
330static struct cfg80211_ops wlan_hdd_cfg80211_ops;
331
332/* Data rate 100KBPS based on IE Index */
333struct index_data_rate_type
334{
335 v_U8_t beacon_rate_index;
336 v_U16_t supported_rate[4];
337};
338
339/* 11B, 11G Rate table include Basic rate and Extended rate
340 The IDX field is the rate index
341 The HI field is the rate when RSSI is strong or being ignored
342 (in this case we report actual rate)
343 The MID field is the rate when RSSI is moderate
344 (in this case we cap 11b rates at 5.5 and 11g rates at 24)
345 The LO field is the rate when RSSI is low
346 (in this case we don't report rates, actual current rate used)
347 */
348static const struct
349{
350 v_U8_t beacon_rate_index;
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700351 v_U16_t supported_rate[4];
Jeff Johnson295189b2012-06-20 16:38:30 -0700352} supported_data_rate[] =
353{
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700354/* IDX HI HM LM LO (RSSI-based index */
355 {2, { 10, 10, 10, 0}},
356 {4, { 20, 20, 10, 0}},
357 {11, { 55, 20, 10, 0}},
358 {12, { 60, 55, 20, 0}},
359 {18, { 90, 55, 20, 0}},
360 {22, {110, 55, 20, 0}},
361 {24, {120, 90, 60, 0}},
362 {36, {180, 120, 60, 0}},
363 {44, {220, 180, 60, 0}},
364 {48, {240, 180, 90, 0}},
365 {66, {330, 180, 90, 0}},
366 {72, {360, 240, 90, 0}},
367 {96, {480, 240, 120, 0}},
368 {108, {540, 240, 120, 0}}
Jeff Johnson295189b2012-06-20 16:38:30 -0700369};
370
371/* MCS Based rate table */
372static struct index_data_rate_type supported_mcs_rate[] =
373{
374/* MCS L20 L40 S20 S40 */
375 {0, {65, 135, 72, 150}},
376 {1, {130, 270, 144, 300}},
377 {2, {195, 405, 217, 450}},
378 {3, {260, 540, 289, 600}},
379 {4, {390, 810, 433, 900}},
380 {5, {520, 1080, 578, 1200}},
381 {6, {585, 1215, 650, 1350}},
382 {7, {650, 1350, 722, 1500}}
383};
384
385extern struct net_device_ops net_ops_struct;
386
387/*
388 * FUNCTION: wlan_hdd_cfg80211_init
389 * This function is called by hdd_wlan_startup()
390 * during initialization.
391 * This function is used to initialize and register wiphy structure.
392 */
393struct wiphy *wlan_hdd_cfg80211_init(int priv_size)
394{
395 struct wiphy *wiphy;
396 ENTER();
397
398 /*
399 * Create wiphy device
400 */
401 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
402
403 if (!wiphy)
404 {
405 /* Print error and jump into err label and free the memory */
406 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__);
407 return NULL;
408 }
409
410 return wiphy;
411}
412
413/*
414 * FUNCTION: wlan_hdd_cfg80211_update_band
415 * This function is called from the supplicant through a
416 * private ioctl to change the band value
417 */
418int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
419{
Jeff Johnsone7245742012-09-05 17:12:55 -0700420 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700421 switch(eBand)
422 {
423 case eCSR_BAND_24:
424 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
425 wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
426 break;
427 case eCSR_BAND_5G:
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700428#ifdef WLAN_FEATURE_P2P
429 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
430#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700431 wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700432#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700433 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
434 break;
435 case eCSR_BAND_ALL:
436 default:
437 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
438 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
439 }
440 return 0;
441}
442/*
443 * FUNCTION: wlan_hdd_cfg80211_init
444 * This function is called by hdd_wlan_startup()
445 * during initialization.
446 * This function is used to initialize and register wiphy structure.
447 */
448int wlan_hdd_cfg80211_register(struct device *dev,
449 struct wiphy *wiphy,
450 hdd_config_t *pCfg
451 )
452{
Jeff Johnsone7245742012-09-05 17:12:55 -0700453 ENTER();
454
Jeff Johnson295189b2012-06-20 16:38:30 -0700455 /* Now bind the underlying wlan device with wiphy */
456 set_wiphy_dev(wiphy, dev);
457
458 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
459
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700460 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700461
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700462#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700463 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
464 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
465 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
Jeff Johnsone7245742012-09-05 17:12:55 -0700466 | WIPHY_FLAG_OFFCHAN_TX;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700467#endif
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700468 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
469 driver can still register regulatory callback and
470 it will get CRDA setting in wiphy->band[], but
471 driver need to determine what to do with both
472 regulatory settings */
473 wiphy->reg_notifier = wlan_hdd_crda_reg_notifier;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700474
Jeff Johnson295189b2012-06-20 16:38:30 -0700475 wiphy->max_scan_ssids = MAX_SCAN_SSID;
476
477 wiphy->max_scan_ie_len = 200 ; //TODO: define a macro
478
479 /* Supports STATION & AD-HOC modes right now */
480 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
481 | BIT(NL80211_IFTYPE_ADHOC)
482#ifdef WLAN_FEATURE_P2P
483 | BIT(NL80211_IFTYPE_P2P_CLIENT)
484 | BIT(NL80211_IFTYPE_P2P_GO)
485#endif
486 | BIT(NL80211_IFTYPE_AP);
487
488 /* Before registering we need to update the ht capabilitied based
489 * on ini values*/
490 if( !pCfg->ShortGI20MhzEnable )
491 {
492 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
493 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
494 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
495 }
496
497 if( !pCfg->ShortGI40MhzEnable )
498 {
499 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
500 }
501
502 if( !pCfg->nChannelBondingMode5GHz )
503 {
504 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
505 }
506
507 /*Initialize band capability*/
508 switch(pCfg->nBandCapability)
509 {
510 case eCSR_BAND_24:
511 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
512 break;
513 case eCSR_BAND_5G:
514#ifdef WLAN_FEATURE_P2P
515 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
516#endif
517 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
518 break;
519 case eCSR_BAND_ALL:
520 default:
521 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
522 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
523 }
524 /*Initialise the supported cipher suite details*/
525 wiphy->cipher_suites = hdd_cipher_suites;
526 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
527
528 /*signal strength in mBm (100*dBm) */
529 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
530
531#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
532#ifdef WLAN_FEATURE_P2P
533 wiphy->max_remain_on_channel_duration = 1000;
534#endif
535#endif
536
537 /* Register our wiphy dev with cfg80211 */
538 if (0 > wiphy_register(wiphy))
539 {
540 /* print eror */
541 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
542 return -EIO;
543 }
544
545 EXIT();
546 return 0;
547}
548
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700549/* In this function we will try to get default country code from crda.
550 If the gCrdaDefaultCountryCode is configured in ini file,
551 we will try to call user space crda to get the regulatory settings for
552 that country. We will timeout if we can't get it from crda.
553 It's called by hdd_wlan_startup() after wlan_hdd_cfg80211_register.
554*/
555int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg)
556{
557 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
558 if (memcmp(pCfg->crdaDefaultCountryCode,
559 CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) != 0)
560 {
561 init_completion(&pHddCtx->driver_crda_req);
562 regulatory_hint(wiphy, pCfg->crdaDefaultCountryCode);
563 wait_for_completion_interruptible_timeout(&pHddCtx->driver_crda_req,
564 CRDA_WAIT_TIME);
565 }
566 return 0;
567}
568
Jeff Johnson295189b2012-06-20 16:38:30 -0700569/* In this function we will do all post VOS start initialization.
570 In this function we will register for all frame in which supplicant
571 is interested.
572*/
573void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
574{
575#ifdef WLAN_FEATURE_P2P
576 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
577 /* Register for all P2P action, public action etc frames */
578 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
579
Jeff Johnsone7245742012-09-05 17:12:55 -0700580 ENTER();
581
Jeff Johnson295189b2012-06-20 16:38:30 -0700582 /* Right now we are registering these frame when driver is getting
583 initialized. Once we will move to 2.6.37 kernel, in which we have
584 frame register ops, we will move this code as a part of that */
585 /* GAS Initial Request */
586 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
587 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
588
589 /* GAS Initial Response */
590 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
591 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
592
593 /* GAS Comeback Request */
594 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
595 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
596
597 /* GAS Comeback Response */
598 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
599 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
600
601 /* P2P Public Action */
602 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
603 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
604 P2P_PUBLIC_ACTION_FRAME_SIZE );
605
606 /* P2P Action */
607 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
608 (v_U8_t*)P2P_ACTION_FRAME,
609 P2P_ACTION_FRAME_SIZE );
610#endif /* WLAN_FEATURE_P2P */
611}
612
613void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
614{
615#ifdef WLAN_FEATURE_P2P
616 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
617 /* Register for all P2P action, public action etc frames */
618 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
619
Jeff Johnsone7245742012-09-05 17:12:55 -0700620 ENTER();
621
Jeff Johnson295189b2012-06-20 16:38:30 -0700622 /* Right now we are registering these frame when driver is getting
623 initialized. Once we will move to 2.6.37 kernel, in which we have
624 frame register ops, we will move this code as a part of that */
625 /* GAS Initial Request */
626
627 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
628 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
629
630 /* GAS Initial Response */
631 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
632 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
633
634 /* GAS Comeback Request */
635 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
636 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
637
638 /* GAS Comeback Response */
639 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
640 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
641
642 /* P2P Public Action */
643 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
644 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
645 P2P_PUBLIC_ACTION_FRAME_SIZE );
646
647 /* P2P Action */
648 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
649 (v_U8_t*)P2P_ACTION_FRAME,
650 P2P_ACTION_FRAME_SIZE );
651#endif /* WLAN_FEATURE_P2P */
652}
653
654#ifdef FEATURE_WLAN_WAPI
655void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
656 const u8 *mac_addr, u8 *key , int key_Len)
657{
658 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
659 tCsrRoamSetKey setKey;
660 v_BOOL_t isConnected = TRUE;
661 int status = 0;
662 v_U32_t roamId= 0xFF;
663 tANI_U8 *pKeyPtr = NULL;
664 int n = 0;
665
666 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
667 __func__,pAdapter->device_mode);
668
669 setKey.keyId = key_index; // Store Key ID
670 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
671 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
672 setKey.paeRole = 0 ; // the PAE role
673 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
674 {
675 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
676 }
677 else
678 {
679 isConnected = hdd_connIsConnected(pHddStaCtx);
680 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
681 }
682 setKey.keyLength = key_Len;
683 pKeyPtr = setKey.Key;
684 memcpy( pKeyPtr, key, key_Len);
685
686 hddLog(VOS_TRACE_LEVEL_INFO,"\n%s: WAPI KEY LENGTH:0x%04x",
687 __func__, key_Len);
688 for (n = 0 ; n < key_Len; n++)
689 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
690 __func__,n,setKey.Key[n]);
691
692 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
693 if ( isConnected )
694 {
695 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
696 pAdapter->sessionId, &setKey, &roamId );
697 }
698 if ( status != 0 )
699 {
700 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
701 "[%4d] sme_RoamSetKey returned ERROR status= %d",
702 __LINE__, status );
703 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
704 }
705}
706#endif /* FEATURE_WLAN_WAPI*/
707
708#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
709int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
710 beacon_data_t **ppBeacon,
711 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700712#else
713int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
714 beacon_data_t **ppBeacon,
715 struct cfg80211_beacon_data *params,
716 int dtim_period)
717#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700718{
719 int size;
720 beacon_data_t *beacon = NULL;
721 beacon_data_t *old = NULL;
722 int head_len,tail_len;
723
Jeff Johnsone7245742012-09-05 17:12:55 -0700724 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700725 if (params->head && !params->head_len)
726 return -EINVAL;
727
728 old = pAdapter->sessionCtx.ap.beacon;
729
730 if (!params->head && !old)
731 return -EINVAL;
732
733 if (params->tail && !params->tail_len)
734 return -EINVAL;
735
736#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
737 /* Kernel 3.0 is not updating dtim_period for set beacon */
738 if (!params->dtim_period)
739 return -EINVAL;
740#endif
741
742 if(params->head)
743 head_len = params->head_len;
744 else
745 head_len = old->head_len;
746
747 if(params->tail || !old)
748 tail_len = params->tail_len;
749 else
750 tail_len = old->tail_len;
751
752 size = sizeof(beacon_data_t) + head_len + tail_len;
753
754 beacon = kzalloc(size, GFP_KERNEL);
755
756 if( beacon == NULL )
757 return -ENOMEM;
758
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700759#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700760 if(params->dtim_period || !old )
761 beacon->dtim_period = params->dtim_period;
762 else
763 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700764#else
765 if(dtim_period || !old )
766 beacon->dtim_period = dtim_period;
767 else
768 beacon->dtim_period = old->dtim_period;
769#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700770
771 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
772 beacon->tail = beacon->head + head_len;
773 beacon->head_len = head_len;
774 beacon->tail_len = tail_len;
775
776 if(params->head) {
777 memcpy (beacon->head,params->head,beacon->head_len);
778 }
779 else {
780 if(old)
781 memcpy (beacon->head,old->head,beacon->head_len);
782 }
783
784 if(params->tail) {
785 memcpy (beacon->tail,params->tail,beacon->tail_len);
786 }
787 else {
788 if(old)
789 memcpy (beacon->tail,old->tail,beacon->tail_len);
790 }
791
792 *ppBeacon = beacon;
793
794 kfree(old);
795
796 return 0;
797
798}
Jeff Johnson295189b2012-06-20 16:38:30 -0700799
800v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
801{
802 int left = length;
803 v_U8_t *ptr = pIes;
804 v_U8_t elem_id,elem_len;
805
806 while(left >= 2)
807 {
808 elem_id = ptr[0];
809 elem_len = ptr[1];
810 left -= 2;
811 if(elem_len > left)
812 {
813 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700814 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -0700815 eid,elem_len,left);
816 return NULL;
817 }
818 if (elem_id == eid)
819 {
820 return ptr;
821 }
822
823 left -= elem_len;
824 ptr += (elem_len + 2);
825 }
826 return NULL;
827}
828
Jeff Johnson295189b2012-06-20 16:38:30 -0700829/* Check if rate is 11g rate or not */
830static int wlan_hdd_rate_is_11g(u8 rate)
831{
832 u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 104}; /* actual rate * 2 */
833 u8 i;
834 for (i = 0; i < 8; i++)
835 {
836 if(rate == gRateArray[i])
837 return TRUE;
838 }
839 return FALSE;
840}
841
842/* Check for 11g rate and set proper 11g only mode */
843static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
844 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
845{
846 u8 i, num_rates = pIe[0];
847
848 pIe += 1;
849 for ( i = 0; i < num_rates; i++)
850 {
851 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
852 {
853 /* If rate set have 11g rate than change the mode to 11G */
854 *pSapHw_mode = eSAP_DOT11_MODE_11g;
855 if (pIe[i] & BASIC_RATE_MASK)
856 {
857 /* If we have 11g rate as basic rate, it means mode
858 is 11g only mode.
859 */
860 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
861 *pCheckRatesfor11g = FALSE;
862 }
863 }
864 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
865 {
866 *require_ht = TRUE;
867 }
868 }
869 return;
870}
871
872static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
873{
874 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
875 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
876 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
877 u8 checkRatesfor11g = TRUE;
878 u8 require_ht = FALSE;
879 u8 *pIe=NULL;
880
881 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
882
883 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
884 pBeacon->head_len, WLAN_EID_SUPP_RATES);
885 if (pIe != NULL)
886 {
887 pIe += 1;
888 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
889 &pConfig->SapHw_mode);
890 }
891
892 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
893 WLAN_EID_EXT_SUPP_RATES);
894 if (pIe != NULL)
895 {
896
897 pIe += 1;
898 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
899 &pConfig->SapHw_mode);
900 }
901
902 if( pConfig->channel > 14 )
903 {
904 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
905 }
906
907 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
908 WLAN_EID_HT_CAPABILITY);
909
910 if(pIe)
911 {
912 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
913 if(require_ht)
914 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
915 }
916}
917
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700918#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700919static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
920 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700921#else
922static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
923 struct cfg80211_beacon_data *params)
924#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700925{
926 v_U8_t *genie;
927 v_U8_t total_ielen = 0, ielen = 0;
928 v_U8_t *pIe = NULL;
929 v_U8_t addIE[1] = {0};
930 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
Jeff Johnsone7245742012-09-05 17:12:55 -0700931 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700932
933 genie = vos_mem_malloc(MAX_GENIE_LEN);
934
935 if(genie == NULL) {
936
937 return -ENOMEM;
938 }
939
940 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
941
942 if(pIe)
943 {
944 /*Copy the wps IE*/
945 ielen = pIe[1] + 2;
946 if( ielen <=MAX_GENIE_LEN)
947 {
948 vos_mem_copy(genie, pIe, ielen);
949 }
950 else
951 {
952 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -0700953 ret = -EINVAL;
954 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -0700955 }
956 total_ielen = ielen;
957 }
958
959#ifdef WLAN_FEATURE_WFD
960 pIe = wlan_hdd_get_wfd_ie_ptr(pBeacon->tail,pBeacon->tail_len);
961
962 if(pIe)
963 {
964 ielen = pIe[1] + 2;
965 if(total_ielen + ielen <= MAX_GENIE_LEN) {
966 vos_mem_copy(&genie[total_ielen],pIe,(pIe[1] + 2));
967 }
968 else {
969 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie + P2p Ie + Wfd Ie Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -0700970 ret = -EINVAL;
971 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -0700972 }
973 total_ielen += ielen;
974 }
975#endif
976
977#ifdef WLAN_FEATURE_P2P
978 pIe = wlan_hdd_get_p2p_ie_ptr(pBeacon->tail,pBeacon->tail_len);
979
980 if(pIe)
981 {
982 ielen = pIe[1] + 2;
983 if(total_ielen + ielen <= MAX_GENIE_LEN)
984 {
985 vos_mem_copy(&genie[total_ielen], pIe, (pIe[1] + 2));
986 }
987 else
988 {
989 hddLog( VOS_TRACE_LEVEL_ERROR,
990 "**Wps Ie+ P2pIE Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -0700991 ret = -EINVAL;
992 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -0700993 }
994 total_ielen += ielen;
995 }
996#endif
997
998 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
999 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1000 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1001 {
1002 hddLog(LOGE,
1003 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001004 ret = -EINVAL;
1005 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001006 }
1007
1008 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1009 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1010 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1011 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1012 ==eHAL_STATUS_FAILURE)
1013 {
1014 hddLog(LOGE,
1015 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001016 ret = -EINVAL;
1017 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001018 }
1019
1020 // Added for ProResp IE
1021 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1022 {
1023 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1024 u8 probe_rsp_ie_len[3] = {0};
1025 u8 counter = 0;
1026 /* Check Probe Resp Length if it is greater then 255 then Store
1027 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1028 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1029 Store More then 255 bytes into One Variable.
1030 */
1031 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1032 {
1033 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1034 {
1035 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1036 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1037 }
1038 else
1039 {
1040 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1041 rem_probe_resp_ie_len = 0;
1042 }
1043 }
1044
1045 rem_probe_resp_ie_len = 0;
1046
1047 if (probe_rsp_ie_len[0] > 0)
1048 {
1049 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1050 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1051 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1052 probe_rsp_ie_len[0], NULL,
1053 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1054 {
1055 hddLog(LOGE,
1056 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001057 ret = -EINVAL;
1058 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001059 }
1060 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1061 }
1062
1063 if (probe_rsp_ie_len[1] > 0)
1064 {
1065 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1066 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1067 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1068 probe_rsp_ie_len[1], NULL,
1069 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1070 {
1071 hddLog(LOGE,
1072 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001073 ret = -EINVAL;
1074 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001075 }
1076 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1077 }
1078
1079 if (probe_rsp_ie_len[2] > 0)
1080 {
1081 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1082 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1083 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1084 probe_rsp_ie_len[2], NULL,
1085 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1086 {
1087 hddLog(LOGE,
1088 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001089 ret = -EINVAL;
1090 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001091 }
1092 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1093 }
1094
1095 if (probe_rsp_ie_len[1] == 0 )
1096 {
1097 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1098 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1099 eANI_BOOLEAN_FALSE) )
1100 {
1101 hddLog(LOGE,
1102 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1103 }
1104 }
1105
1106 if (probe_rsp_ie_len[2] == 0 )
1107 {
1108 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1109 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1110 eANI_BOOLEAN_FALSE) )
1111 {
1112 hddLog(LOGE,
1113 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1114 }
1115 }
1116
1117 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1118 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1119 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1120 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1121 == eHAL_STATUS_FAILURE)
1122 {
1123 hddLog(LOGE,
1124 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001125 ret = -EINVAL;
1126 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001127 }
1128 }
1129 else
1130 {
1131 // Reset WNI_CFG_PROBE_RSP Flags
1132 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1133
1134 hddLog(VOS_TRACE_LEVEL_INFO,
1135 "%s: No Probe Response IE received in set beacon",
1136 __func__);
1137 }
1138
1139 // Added for AssocResp IE
1140 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1141 {
1142 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1143 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1144 params->assocresp_ies_len, NULL,
1145 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1146 {
1147 hddLog(LOGE,
1148 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001149 ret = -EINVAL;
1150 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001151 }
1152
1153 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1154 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1155 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1156 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1157 == eHAL_STATUS_FAILURE)
1158 {
1159 hddLog(LOGE,
1160 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001161 ret = -EINVAL;
1162 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001163 }
1164 }
1165 else
1166 {
1167 hddLog(VOS_TRACE_LEVEL_INFO,
1168 "%s: No Assoc Response IE received in set beacon",
1169 __func__);
1170
1171 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1172 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1173 eANI_BOOLEAN_FALSE) )
1174 {
1175 hddLog(LOGE,
1176 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1177 }
1178 }
1179
Jeff Johnsone7245742012-09-05 17:12:55 -07001180done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001181 vos_mem_free(genie);
1182 return 0;
1183}
Jeff Johnson295189b2012-06-20 16:38:30 -07001184
1185/*
1186 * FUNCTION: wlan_hdd_validate_operation_channel
1187 * called by wlan_hdd_cfg80211_start_bss() and
1188 * wlan_hdd_cfg80211_set_channel()
1189 * This function validates whether given channel is part of valid
1190 * channel list.
1191 */
1192static VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
1193{
1194
1195 v_U32_t num_ch = 0;
1196 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1197 u32 indx = 0;
1198 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1199
1200 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1201
1202 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1203 valid_ch, &num_ch))
1204 {
1205 hddLog(VOS_TRACE_LEVEL_ERROR,
1206 "%s: failed to get valid channel list\n", __func__);
1207 return VOS_STATUS_E_FAILURE;
1208 }
1209
1210 for (indx = 0; indx < num_ch; indx++)
1211 {
1212 if (channel == valid_ch[indx])
1213 {
1214 break;
1215 }
1216 }
1217
1218 if (indx >= num_ch)
1219 {
1220 hddLog(VOS_TRACE_LEVEL_ERROR,
1221 "%s: Invalid Channel [%d] \n", __func__, channel);
1222 return VOS_STATUS_E_FAILURE;
1223 }
1224 return VOS_STATUS_SUCCESS;
1225
1226}
1227
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001228
Jeff Johnson295189b2012-06-20 16:38:30 -07001229#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1230static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1231 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001232#else
1233static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1234 struct cfg80211_beacon_data *params,
1235 const u8 *ssid, size_t ssid_len,
1236 enum nl80211_hidden_ssid hidden_ssid)
1237#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001238{
1239 tsap_Config_t *pConfig;
1240 beacon_data_t *pBeacon = NULL;
1241 struct ieee80211_mgmt *pMgmt_frame;
1242 v_U8_t *pIe=NULL;
1243 v_U16_t capab_info;
1244 eCsrAuthType RSNAuthType;
1245 eCsrEncryptionType RSNEncryptType;
1246 eCsrEncryptionType mcRSNEncryptType;
1247 int status = VOS_STATUS_SUCCESS;
1248 tpWLAN_SAPEventCB pSapEventCallback;
1249 hdd_hostapd_state_t *pHostapdState;
1250 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1251 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
1252 struct qc_mac_acl_entry *acl_entry = NULL;
1253 v_SINT_t i;
1254
1255 ENTER();
1256
1257 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1258
1259 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1260
1261 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1262
1263 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1264
1265 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1266
1267 //channel is already set in the set_channel Call back
1268 //pConfig->channel = pCommitConfig->channel;
1269
1270 /*Protection parameter to enable or disable*/
1271 pConfig->protEnabled =
1272 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1273
1274 pConfig->dtim_period = pBeacon->dtim_period;
1275
1276 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1277 pConfig->dtim_period);
1278
1279
Jeff Johnson32d95a32012-09-10 13:15:23 -07001280 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
1281 {
1282 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001283 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001284 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001285 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001286 tANI_BOOLEAN restartNeeded;
1287 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
1288 pConfig->ieee80211d = 1;
1289 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1290 sme_setRegInfo(hHal, pConfig->countryCode);
1291 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
1292 /*
1293 * If auto channel is configured i.e. channel is 0,
1294 * so skip channel validation.
1295 */
1296 if( AUTO_CHANNEL_SELECT != pConfig->channel )
Jeff Johnson295189b2012-06-20 16:38:30 -07001297 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001298 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1299 {
1300 hddLog(VOS_TRACE_LEVEL_ERROR,
1301 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1302 return -EINVAL;
1303 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001304 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001305 /*
1306 * Validate the given channel range for the given country code
1307 */
1308 else
1309 {
1310 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
1311 WLANSAP_SetChannelRange(hHal,hdd_pConfig->apStartChannelNum,hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
1312 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001313 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001314 else
1315 {
1316 pConfig->ieee80211d = 0;
1317 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001318 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001319 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001320 {
1321 pConfig->ieee80211d = 0;
1322 }
1323 pConfig->authType = eSAP_AUTO_SWITCH;
1324
1325 capab_info = pMgmt_frame->u.beacon.capab_info;
1326
1327 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
1328 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1329
1330 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1331
1332 /*Set wps station to configured*/
1333 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1334
1335 if(pIe)
1336 {
1337 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1338 {
1339 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1340 return -EINVAL;
1341 }
1342 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1343 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001344 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001345 /* Check 15 bit of WPS IE as it contain information for wps state
1346 * WPS state
1347 */
1348 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1349 {
1350 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1351 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1352 {
1353 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1354 }
1355 }
1356 }
1357 else
1358 {
1359 pConfig->wps_state = SAP_WPS_DISABLED;
1360 }
1361 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
1362
1363 pConfig->RSNWPAReqIELength = 0;
1364 pConfig->pRSNWPAReqIE = NULL;
1365 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1366 WLAN_EID_RSN);
1367 if(pIe && pIe[1])
1368 {
1369 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1370 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1371 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1372 /* The actual processing may eventually be more extensive than
1373 * this. Right now, just consume any PMKIDs that are sent in
1374 * by the app.
1375 * */
1376 status = hdd_softap_unpackIE(
1377 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1378 &RSNEncryptType,
1379 &mcRSNEncryptType,
1380 &RSNAuthType,
1381 pConfig->pRSNWPAReqIE[1]+2,
1382 pConfig->pRSNWPAReqIE );
1383
1384 if( VOS_STATUS_SUCCESS == status )
1385 {
1386 /* Now copy over all the security attributes you have
1387 * parsed out
1388 * */
1389 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1390 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1391 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1392 = RSNEncryptType;
1393 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1394 "EncryptionType = %d mcEncryptionType = %d\n"),
1395 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1396 }
1397 }
1398
1399 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1400 pBeacon->tail, pBeacon->tail_len);
1401
1402 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1403 {
1404 if (pConfig->pRSNWPAReqIE)
1405 {
1406 /*Mixed mode WPA/WPA2*/
1407 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1408 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1409 }
1410 else
1411 {
1412 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1413 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1414 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1415 status = hdd_softap_unpackIE(
1416 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1417 &RSNEncryptType,
1418 &mcRSNEncryptType,
1419 &RSNAuthType,
1420 pConfig->pRSNWPAReqIE[1]+2,
1421 pConfig->pRSNWPAReqIE );
1422
1423 if( VOS_STATUS_SUCCESS == status )
1424 {
1425 /* Now copy over all the security attributes you have
1426 * parsed out
1427 * */
1428 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1429 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1430 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1431 = RSNEncryptType;
1432 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1433 "EncryptionType = %d mcEncryptionType = %d\n"),
1434 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1435 }
1436 }
1437 }
1438
1439 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1440
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001441#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001442 if (params->ssid != NULL)
1443 {
1444 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1445 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1446 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1447 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1448 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001449#else
1450 if (ssid != NULL)
1451 {
1452 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1453 pConfig->SSIDinfo.ssid.length = ssid_len;
1454 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1455 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1456 }
1457#endif
1458
Jeff Johnson295189b2012-06-20 16:38:30 -07001459 vos_mem_copy(pConfig->self_macaddr.bytes,
1460 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1461
1462 /* default value */
1463 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1464 pConfig->num_accept_mac = 0;
1465 pConfig->num_deny_mac = 0;
1466
1467 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1468 pBeacon->tail, pBeacon->tail_len);
1469
1470 /* pIe for black list is following form:
1471 type : 1 byte
1472 length : 1 byte
1473 OUI : 4 bytes
1474 acl type : 1 byte
1475 no of mac addr in black list: 1 byte
1476 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1477 */
1478 if ((pIe != NULL) && (pIe[1] != 0))
1479 {
1480 pConfig->SapMacaddr_acl = pIe[6];
1481 pConfig->num_deny_mac = pIe[7];
1482 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1483 pIe[6], pIe[7]);
1484 if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
1485 pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
1486 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1487 for (i = 0; i < pConfig->num_deny_mac; i++)
1488 {
1489 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1490 acl_entry++;
1491 }
1492 }
1493 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1494 pBeacon->tail, pBeacon->tail_len);
1495
1496 /* pIe for white list is following form:
1497 type : 1 byte
1498 length : 1 byte
1499 OUI : 4 bytes
1500 acl type : 1 byte
1501 no of mac addr in white list: 1 byte
1502 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1503 */
1504 if ((pIe != NULL) && (pIe[1] != 0))
1505 {
1506 pConfig->SapMacaddr_acl = pIe[6];
1507 pConfig->num_accept_mac = pIe[7];
1508 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
1509 pIe[6], pIe[7]);
1510 if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
1511 pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
1512 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1513 for (i = 0; i < pConfig->num_accept_mac; i++)
1514 {
1515 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1516 acl_entry++;
1517 }
1518 }
1519 wlan_hdd_set_sapHwmode(pHostapdAdapter);
1520
Jeff Johnsone7245742012-09-05 17:12:55 -07001521#ifdef WLAN_FEATURE_11AC
1522 if(((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
1523 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1524 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) )
1525 {
1526 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
1527 }
1528#endif
1529
Jeff Johnson295189b2012-06-20 16:38:30 -07001530 // ht_capab is not what the name conveys,this is used for protection bitmap
1531 pConfig->ht_capab =
1532 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
1533
1534 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
1535 {
1536 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
1537 return -EINVAL;
1538 }
1539
1540 //Uapsd Enabled Bit
1541 pConfig->UapsdEnable =
1542 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
1543 //Enable OBSS protection
1544 pConfig->obssProtEnabled =
1545 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
1546
1547 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
1548 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
1549 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
1550 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
1551 (int)pConfig->channel);
1552 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
1553 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
1554 pConfig->authType);
1555 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
1556 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
1557 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
1558 pConfig->protEnabled, pConfig->obssProtEnabled);
1559
1560 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
1561 {
1562 //Bss already started. just return.
1563 //TODO Probably it should update some beacon params.
1564 hddLog( LOGE, "Bss Already started...Ignore the request");
1565 EXIT();
1566 return 0;
1567 }
1568
1569 pConfig->persona = pHostapdAdapter->device_mode;
1570
1571 pSapEventCallback = hdd_hostapd_SAPEventCB;
1572 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
1573 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
1574 {
1575 hddLog(LOGE,FL("SAP Start Bss fail\n"));
1576 return -EINVAL;
1577 }
1578
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001579 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07001580 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
1581
1582 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1583
1584 if (!VOS_IS_STATUS_SUCCESS(status))
1585 {
1586 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1587 ("ERROR: HDD vos wait for single_event failed!!\n"));
1588 VOS_ASSERT(0);
1589 }
1590
1591 //Succesfully started Bss update the state bit.
1592 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
1593
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001594#ifdef WLAN_FEATURE_P2P_DEBUG
1595 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
1596 {
1597 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
1598 {
1599 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1600 hddLog(LOGE,"[P2P State] From Go nego completed to "
1601 "Non-autonomus Group started");
1602 }
1603 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
1604 {
1605 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1606 hddLog(LOGE,"[P2P State] From Inactive to "
1607 "Autonomus Group started");
1608 }
1609 }
1610#endif
1611
Jeff Johnson295189b2012-06-20 16:38:30 -07001612 pHostapdState->bCommit = TRUE;
1613 EXIT();
1614
1615 return 0;
1616}
1617
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001618#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001619static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
1620 struct net_device *dev,
1621 struct beacon_parameters *params)
1622{
1623 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1624 int status=VOS_STATUS_SUCCESS;
1625
1626 ENTER();
1627
1628 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
1629
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001630 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1631 {
1632 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1633 "%s:LOGP in Progress. Ignore!!!", __func__);
1634 return -EAGAIN;
1635 }
1636
Jeff Johnson295189b2012-06-20 16:38:30 -07001637 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
1638#ifdef WLAN_FEATURE_P2P
1639 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1640#endif
1641 )
1642 {
1643 beacon_data_t *old,*new;
1644
1645 old = pAdapter->sessionCtx.ap.beacon;
1646
1647 if (old)
1648 return -EALREADY;
1649
1650 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
1651
1652 if(status != VOS_STATUS_SUCCESS)
1653 {
1654 hddLog(VOS_TRACE_LEVEL_FATAL,
1655 "%s:Error!!! Allocating the new beacon\n",__func__);
1656 return -EINVAL;
1657 }
1658
1659 pAdapter->sessionCtx.ap.beacon = new;
1660
1661 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
1662 }
1663
1664 EXIT();
1665 return status;
1666}
1667
1668static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
1669 struct net_device *dev,
1670 struct beacon_parameters *params)
1671{
1672 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1673 int status=VOS_STATUS_SUCCESS;
1674
1675 ENTER();
1676
1677 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1678 __func__,pAdapter->device_mode);
1679
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001680 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1681 {
1682 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1683 "%s:LOGP in Progress. Ignore!!!", __func__);
1684 return -EAGAIN;
1685 }
1686
Jeff Johnson295189b2012-06-20 16:38:30 -07001687 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1688#ifdef WLAN_FEATURE_P2P
1689 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1690#endif
1691 )
1692 {
1693 beacon_data_t *old,*new;
1694
1695 old = pAdapter->sessionCtx.ap.beacon;
1696
1697 if (!old)
1698 return -ENOENT;
1699
1700 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
1701
1702 if(status != VOS_STATUS_SUCCESS) {
1703 hddLog(VOS_TRACE_LEVEL_FATAL,
1704 "%s: Error!!! Allocating the new beacon\n",__func__);
1705 return -EINVAL;
1706 }
1707
1708 pAdapter->sessionCtx.ap.beacon = new;
1709
1710 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
1711 }
1712
1713 EXIT();
1714 return status;
1715}
1716
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001717#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1718
1719#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001720static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
1721 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001722#else
1723static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
1724 struct net_device *dev)
1725#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001726{
1727 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07001728 hdd_context_t *pHddCtx = NULL;
1729 hdd_scaninfo_t *pScanInfo = NULL;
1730 hdd_adapter_t *staAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001731 VOS_STATUS status = 0;
1732
1733 ENTER();
1734
1735 if (NULL == pAdapter)
1736 {
1737 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001738 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001739 return -ENODEV;
1740 }
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001741 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1742 {
1743 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1744 "%s:LOGP in Progress. Ignore!!!", __func__);
1745 return -EAGAIN;
1746 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001747
1748 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1749 if (NULL == pHddCtx)
1750 {
1751 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001752 "%s: HDD context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001753 return -ENODEV;
1754 }
1755
1756 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
1757 if (NULL == staAdapter)
1758 {
1759 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
1760 if (NULL == staAdapter)
1761 {
1762 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001763 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001764 return -ENODEV;
1765 }
1766 }
1767
1768 pScanInfo = &pHddCtx->scan_info;
1769
Jeff Johnson295189b2012-06-20 16:38:30 -07001770 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1771 {
1772 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1773 return -EAGAIN;
1774 }
1775
1776 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1777
1778 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1779 __func__,pAdapter->device_mode);
1780
Jeff Johnsone7245742012-09-05 17:12:55 -07001781 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
1782 {
1783 INIT_COMPLETION(staAdapter->abortscan_event_var);
1784 hdd_abort_mac_scan(staAdapter->pHddCtx);
1785 status = wait_for_completion_interruptible_timeout(
1786 &staAdapter->abortscan_event_var,
1787 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
1788 if (!status)
1789 {
1790 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1791 "%s: Timeout occured while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001792 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07001793 VOS_ASSERT(pScanInfo->mScanPending);
1794 return 0;
1795 }
1796 }
1797
Jeff Johnson295189b2012-06-20 16:38:30 -07001798 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1799#ifdef WLAN_FEATURE_P2P
1800 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1801#endif
1802 )
1803 {
1804 beacon_data_t *old;
1805
1806 old = pAdapter->sessionCtx.ap.beacon;
1807
1808 if (!old)
1809 return -ENOENT;
1810
1811#ifdef CONFIG_CFG80211
1812 hdd_cleanup_actionframe(pHddCtx, pAdapter);
1813#endif
1814
1815 mutex_lock(&pHddCtx->sap_lock);
1816 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
1817 {
1818 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss((WLAN_HDD_GET_CTX(pAdapter))->pvosContext) ) )
1819 {
1820 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
1821
1822 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1823
1824 if (!VOS_IS_STATUS_SUCCESS(status))
1825 {
1826 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1827 ("ERROR: HDD vos wait for single_event failed!!\n"));
1828 VOS_ASSERT(0);
1829 }
1830 }
1831 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
1832 }
1833 mutex_unlock(&pHddCtx->sap_lock);
1834
1835 if(status != VOS_STATUS_SUCCESS)
1836 {
1837 hddLog(VOS_TRACE_LEVEL_FATAL,
1838 "%s:Error!!! Stopping the BSS\n",__func__);
1839 return -EINVAL;
1840 }
1841
1842 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
1843 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
1844 ==eHAL_STATUS_FAILURE)
1845 {
1846 hddLog(LOGE,
1847 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
1848 }
1849
1850 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
1851 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1852 eANI_BOOLEAN_FALSE) )
1853 {
1854 hddLog(LOGE,
1855 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1856 }
1857
1858 // Reset WNI_CFG_PROBE_RSP Flags
1859 wlan_hdd_reset_prob_rspies(pAdapter);
1860
1861 pAdapter->sessionCtx.ap.beacon = NULL;
1862 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001863#ifdef WLAN_FEATURE_P2P_DEBUG
1864 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
1865 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
1866 {
1867 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
1868 "GO got removed");
1869 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
1870 }
1871#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001872 }
1873 EXIT();
1874 return status;
1875}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001876
1877#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
1878
1879static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
1880 struct net_device *dev,
1881 struct cfg80211_ap_settings *params)
1882{
1883 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1884 int status = VOS_STATUS_SUCCESS;
1885
1886 ENTER();
1887
1888 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n", pAdapter->device_mode);
1889
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001890 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1891 {
1892 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1893 return -EAGAIN;
1894 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001895 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1896#ifdef WLAN_FEATURE_P2P
1897 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1898#endif
1899 )
1900 {
1901 beacon_data_t *old,*new;
1902
1903 old = pAdapter->sessionCtx.ap.beacon;
1904
1905 if (old)
1906 return -EALREADY;
1907
1908 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
1909
1910 if(status != VOS_STATUS_SUCCESS)
1911 {
1912 hddLog(VOS_TRACE_LEVEL_FATAL,
1913 "%s:Error!!! Allocating the new beacon\n",__func__);
1914 return -EINVAL;
1915 }
1916 pAdapter->sessionCtx.ap.beacon = new;
1917 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
1918 params->ssid_len, params->hidden_ssid);
1919 }
1920
1921 EXIT();
1922 return status;
1923}
1924
1925
1926static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
1927 struct net_device *dev,
1928 struct cfg80211_beacon_data *params)
1929{
1930 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1931 int status=VOS_STATUS_SUCCESS;
1932
1933 ENTER();
1934
1935 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1936 __func__, pAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001937 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1938 {
1939 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1940 return -EAGAIN;
1941 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001942
1943 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1944#ifdef WLAN_FEATURE_P2P
1945 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1946#endif
1947 )
1948 {
1949 beacon_data_t *old,*new;
1950
1951 old = pAdapter->sessionCtx.ap.beacon;
1952
1953 if (!old)
1954 return -ENOENT;
1955
1956 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
1957
1958 if(status != VOS_STATUS_SUCCESS) {
1959 hddLog(VOS_TRACE_LEVEL_FATAL,
1960 "%s: Error!!! Allocating the new beacon\n",__func__);
1961 return -EINVAL;
1962 }
1963
1964 pAdapter->sessionCtx.ap.beacon = new;
1965
1966 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
1967 }
1968
1969 EXIT();
1970 return status;
1971}
1972
1973#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
1974
Jeff Johnson295189b2012-06-20 16:38:30 -07001975
1976static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
1977 struct net_device *dev,
1978 struct bss_parameters *params)
1979{
1980 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1981
1982 ENTER();
1983
1984 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1985 __func__,pAdapter->device_mode);
1986
1987 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1988#ifdef WLAN_FEATURE_P2P
1989 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1990#endif
1991 )
1992 {
1993 /* ap_isolate == -1 means that in change bss, upper layer doesn't
1994 * want to update this parameter */
1995 if (-1 != params->ap_isolate)
1996 {
1997 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
1998 }
1999 }
2000
2001 EXIT();
2002 return 0;
2003}
2004
2005/*
2006 * FUNCTION: wlan_hdd_cfg80211_change_iface
2007 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2008 */
2009int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2010 struct net_device *ndev,
2011 enum nl80211_iftype type,
2012 u32 *flags,
2013 struct vif_params *params
2014 )
2015{
2016 struct wireless_dev *wdev;
2017 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2018 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002019 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002020 tCsrRoamProfile *pRoamProfile = NULL;
2021 eCsrRoamBssType LastBSSType;
2022 hdd_config_t *pConfig = pHddCtx->cfg_ini;
2023 eMib_dot11DesiredBssType connectedBssType;
2024 VOS_STATUS status;
2025
2026 ENTER();
2027
2028 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2029 {
2030 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2031 return -EAGAIN;
2032 }
2033
2034 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2035 __func__, pAdapter->device_mode);
2036
2037 wdev = ndev->ieee80211_ptr;
2038
2039#ifdef WLAN_BTAMP_FEATURE
2040 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2041 (NL80211_IFTYPE_ADHOC == type)||
2042 (NL80211_IFTYPE_AP == type)||
2043 (NL80211_IFTYPE_P2P_GO == type))
2044 {
2045 pHddCtx->isAmpAllowed = VOS_FALSE;
2046 // stop AMP traffic
2047 status = WLANBAP_StopAmp();
2048 if(VOS_STATUS_SUCCESS != status )
2049 {
2050 pHddCtx->isAmpAllowed = VOS_TRUE;
2051 hddLog(VOS_TRACE_LEVEL_FATAL,
2052 "%s: Failed to stop AMP", __func__);
2053 return -EINVAL;
2054 }
2055 }
2056#endif //WLAN_BTAMP_FEATURE
2057 /* Reset the current device mode bit mask*/
2058 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2059
2060 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2061#ifdef WLAN_FEATURE_P2P
2062 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002063 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002064#endif
2065 )
2066 {
2067 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2068 pRoamProfile = &pWextState->roamProfile;
2069 LastBSSType = pRoamProfile->BSSType;
2070
2071 switch (type)
2072 {
2073 case NL80211_IFTYPE_STATION:
2074#ifdef WLAN_FEATURE_P2P
2075 case NL80211_IFTYPE_P2P_CLIENT:
2076#endif
2077 hddLog(VOS_TRACE_LEVEL_INFO,
2078 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2079 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002080#ifdef WLAN_FEATURE_11AC
2081 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2082 {
2083 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2084 }
2085#endif
2086 pRoamProfile->phyMode =
2087 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002088 wdev->iftype = type;
2089#ifdef WLAN_FEATURE_P2P
2090 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2091 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
2092#endif
2093 break;
2094 case NL80211_IFTYPE_ADHOC:
2095 hddLog(VOS_TRACE_LEVEL_INFO,
2096 "%s: setting interface Type to ADHOC", __func__);
2097 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2098 pRoamProfile->phyMode =
2099 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
2100 wdev->iftype = type;
2101 break;
2102
2103 case NL80211_IFTYPE_AP:
2104#ifdef WLAN_FEATURE_P2P
2105 case NL80211_IFTYPE_P2P_GO:
2106#endif
2107 {
2108 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2109 "%s: setting interface Type to %s", __func__,
2110 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2111
Mohit Khanna0f232092012-09-11 14:46:08 -07002112 if (NL80211_IFTYPE_AP == type)
2113 {
2114 /* As Loading WLAN Driver one interface being created for p2p device
2115 * address. This will take one HW STA and the max number of clients
2116 * that can connect to softAP will be reduced by one. so while changing
2117 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2118 * interface as it is not required in SoftAP mode.
2119 */
2120
2121 // Get P2P Adapter
2122 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2123
2124 if (pP2pAdapter)
2125 {
2126 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2127 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2128 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2129 }
2130 }
2131
Jeff Johnson295189b2012-06-20 16:38:30 -07002132 //De-init the adapter.
2133 hdd_stop_adapter( pHddCtx, pAdapter );
2134 hdd_deinit_adapter( pHddCtx, pAdapter );
2135 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2136#ifdef WLAN_SOFTAP_FEATURE
2137#ifdef WLAN_FEATURE_P2P
2138 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2139 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2140#else
2141 pAdapter->device_mode = WLAN_HDD_SOFTAP;
2142#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07002143
2144 //Disable BMPS and IMPS if enabled
2145 //before starting Go
2146 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2147 {
2148 if(VOS_STATUS_E_FAILURE ==
2149 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2150 {
2151 //Fail to Exit BMPS
2152 VOS_ASSERT(0);
2153 }
2154 }
2155
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002156 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2157 (pConfig->apRandomBssidEnabled))
2158 {
2159 /* To meet Android requirements create a randomized
2160 MAC address of the form 02:1A:11:Fx:xx:xx */
2161 get_random_bytes(&ndev->dev_addr[3], 3);
2162 ndev->dev_addr[0] = 0x02;
2163 ndev->dev_addr[1] = 0x1A;
2164 ndev->dev_addr[2] = 0x11;
2165 ndev->dev_addr[3] |= 0xF0;
2166 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2167 VOS_MAC_ADDR_SIZE);
2168 pr_info("wlan: Generated HotSpot BSSID "
2169 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2170 ndev->dev_addr[0],
2171 ndev->dev_addr[1],
2172 ndev->dev_addr[2],
2173 ndev->dev_addr[3],
2174 ndev->dev_addr[4],
2175 ndev->dev_addr[5]);
2176 }
2177
Jeff Johnson295189b2012-06-20 16:38:30 -07002178 hdd_set_ap_ops( pAdapter->dev );
2179
2180 status = hdd_init_ap_mode(pAdapter);
2181 if(status != VOS_STATUS_SUCCESS)
2182 {
2183 hddLog(VOS_TRACE_LEVEL_FATAL,
2184 "%s: Error initializing the ap mode", __func__);
2185 return -EINVAL;
2186 }
2187 hdd_set_conparam(1);
2188
2189#endif
2190 /*interface type changed update in wiphy structure*/
2191 if(wdev)
2192 {
2193 wdev->iftype = type;
2194 pHddCtx->change_iface = type;
2195 }
2196 else
2197 {
2198 hddLog(VOS_TRACE_LEVEL_ERROR,
2199 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2200 return -EINVAL;
2201 }
2202 goto done;
2203 }
2204
2205 default:
2206 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2207 __func__);
2208 return -EOPNOTSUPP;
2209 }
2210 }
2211 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
2212#ifdef WLAN_FEATURE_P2P
2213 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2214#endif
2215 )
2216 {
2217 switch(type)
2218 {
2219 case NL80211_IFTYPE_STATION:
2220#ifdef WLAN_FEATURE_P2P
2221 case NL80211_IFTYPE_P2P_CLIENT:
2222#endif
2223 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002224 hdd_stop_adapter( pHddCtx, pAdapter );
2225 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002226 wdev->iftype = type;
2227#ifdef WLAN_FEATURE_P2P
2228 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2229 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
2230#endif
2231 hdd_set_conparam(0);
2232 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002233 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2234 hdd_set_station_ops( pAdapter->dev );
2235 status = hdd_init_station_mode( pAdapter );
2236 if( VOS_STATUS_SUCCESS != status )
2237 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002238 /* In case of JB, for P2P-GO, only change interface will be called,
2239 * This is the right place to enable back bmps_imps()
2240 */
2241 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002242 goto done;
2243 case NL80211_IFTYPE_AP:
2244#ifdef WLAN_FEATURE_P2P
2245 case NL80211_IFTYPE_P2P_GO:
2246#endif
2247 wdev->iftype = type;
2248#ifdef WLAN_FEATURE_P2P
2249 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2250 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2251#endif
2252 goto done;
2253 default:
2254 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2255 __func__);
2256 return -EOPNOTSUPP;
2257
2258 }
2259
2260 }
2261 else
2262 {
2263 return -EOPNOTSUPP;
2264 }
2265
2266
2267 if(pRoamProfile)
2268 {
2269 if ( LastBSSType != pRoamProfile->BSSType )
2270 {
2271 /*interface type changed update in wiphy structure*/
2272 wdev->iftype = type;
2273
2274 /*the BSS mode changed, We need to issue disconnect
2275 if connected or in IBSS disconnect state*/
2276 if ( hdd_connGetConnectedBssType(
2277 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2278 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2279 {
2280 /*need to issue a disconnect to CSR.*/
2281 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2282 if( eHAL_STATUS_SUCCESS ==
2283 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2284 pAdapter->sessionId,
2285 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2286 {
2287 wait_for_completion_interruptible_timeout(
2288 &pAdapter->disconnect_comp_var,
2289 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2290 }
2291 }
2292 }
2293 }
2294
2295done:
2296 /*set bitmask based on updated value*/
2297 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
2298#ifdef WLAN_BTAMP_FEATURE
2299 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
2300 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2301 {
2302 //we are ok to do AMP
2303 pHddCtx->isAmpAllowed = VOS_TRUE;
2304 }
2305#endif //WLAN_BTAMP_FEATURE
2306 EXIT();
2307 return 0;
2308}
2309
2310static int wlan_hdd_change_station(struct wiphy *wiphy,
2311 struct net_device *dev,
2312 u8 *mac,
2313 struct station_parameters *params)
2314{
2315 VOS_STATUS status = VOS_STATUS_SUCCESS;
2316 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2317 v_MACADDR_t STAMacAddress;
2318
Jeff Johnsone7245742012-09-05 17:12:55 -07002319 ENTER();
2320
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002321 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2322 {
2323 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2324 "%s:LOGP in Progress. Ignore!!!", __func__);
2325 return -EAGAIN;
2326 }
2327
Jeff Johnson295189b2012-06-20 16:38:30 -07002328 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
2329
2330 if ( ( pAdapter->device_mode == WLAN_HDD_SOFTAP )
2331#ifdef WLAN_FEATURE_P2P
2332 || ( pAdapter->device_mode == WLAN_HDD_P2P_GO )
2333#endif
2334 )
2335 {
2336 if(params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
2337 {
2338 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
2339 WLANTL_STA_AUTHENTICATED);
2340
2341 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002342 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002343 return -EINVAL;
2344 }
2345 }
2346
Jeff Johnsone7245742012-09-05 17:12:55 -07002347 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002348 return status;
2349}
2350
2351/*
2352 * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
2353 * This function is used to get peer station index in IBSS mode
2354 */
2355static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
2356{
2357 u8 idx = 0;
2358 u8 temp[VOS_MAC_ADDR_SIZE] = {0};
2359 ENTER();
2360 memset(temp, 0, VOS_MAC_ADDR_SIZE);
2361 for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
2362 {
2363 if ( (0 !=
2364 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
2365 && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
2366 temp, VOS_MAC_ADDR_SIZE)
2367 )
2368 {
2369 return idx;
2370 }
2371 }
2372 return idx;
2373}
2374
2375
2376/*
2377 * FUNCTION: wlan_hdd_cfg80211_add_key
2378 * This function is used to initialize the key information
2379 */
2380#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2381static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2382 struct net_device *ndev,
2383 u8 key_index, bool pairwise,
2384 const u8 *mac_addr,
2385 struct key_params *params
2386 )
2387#else
2388static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2389 struct net_device *ndev,
2390 u8 key_index, const u8 *mac_addr,
2391 struct key_params *params
2392 )
2393#endif
2394{
2395 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2396 tCsrRoamSetKey setKey;
2397 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
2398 int status = 0;
2399 v_U32_t roamId= 0xFF;
2400 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2401 hdd_hostapd_state_t *pHostapdState;
2402 VOS_STATUS vos_status;
2403
2404 ENTER();
2405
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002406 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2407 {
2408 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2409 "%s:LOGP in Progress. Ignore!!!", __func__);
2410 return -EAGAIN;
2411 }
2412
Jeff Johnson295189b2012-06-20 16:38:30 -07002413 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2414 __func__,pAdapter->device_mode);
2415
2416 if (CSR_MAX_NUM_KEY <= key_index)
2417 {
2418 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
2419 key_index);
2420
2421 return -EINVAL;
2422 }
2423
2424 hddLog(VOS_TRACE_LEVEL_INFO,
2425 "%s: called with key index = %d & key length %d",
2426 __func__, key_index, params->key_len);
2427
2428 /*extract key idx, key len and key*/
2429 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2430 setKey.keyId = key_index;
2431 setKey.keyLength = params->key_len;
2432 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
2433
2434 switch (params->cipher)
2435 {
2436 case WLAN_CIPHER_SUITE_WEP40:
2437 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
2438 break;
2439
2440 case WLAN_CIPHER_SUITE_WEP104:
2441 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
2442 break;
2443
2444 case WLAN_CIPHER_SUITE_TKIP:
2445 {
2446 u8 *pKey = &setKey.Key[0];
2447 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
2448
2449 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
2450
2451 /*Supplicant sends the 32bytes key in this order
2452
2453 |--------------|----------|----------|
2454 | Tk1 |TX-MIC | RX Mic |
2455 |--------------|----------|----------|
2456 <---16bytes---><--8bytes--><--8bytes-->
2457
2458 */
2459 /*Sme expects the 32 bytes key to be in the below order
2460
2461 |--------------|----------|----------|
2462 | Tk1 |RX-MIC | TX Mic |
2463 |--------------|----------|----------|
2464 <---16bytes---><--8bytes--><--8bytes-->
2465 */
2466 /* Copy the Temporal Key 1 (TK1) */
2467 vos_mem_copy(pKey, params->key,16);
2468
2469 /*Copy the rx mic first*/
2470 vos_mem_copy(&pKey[16],&params->key[24],8);
2471
2472 /*Copy the tx mic */
2473 vos_mem_copy(&pKey[24],&params->key[16],8);
2474
2475
2476 break;
2477 }
2478
2479 case WLAN_CIPHER_SUITE_CCMP:
2480 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
2481 break;
2482
2483#ifdef FEATURE_WLAN_WAPI
2484 case WLAN_CIPHER_SUITE_SMS4:
2485 {
2486 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2487 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
2488 params->key, params->key_len);
2489 return 0;
2490 }
2491#endif
2492#ifdef FEATURE_WLAN_CCX
2493 case WLAN_CIPHER_SUITE_KRK:
2494 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
2495 break;
2496#endif
2497 default:
2498 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
2499 __func__, params->cipher);
2500 return -EOPNOTSUPP;
2501 }
2502
2503 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
2504 __func__, setKey.encType);
2505
2506
2507
2508 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2509#ifdef WLAN_FEATURE_P2P
2510 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2511#endif
2512 )
2513 {
2514
2515
2516 if (
2517#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2518 (!pairwise)
2519#else
2520 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2521#endif
2522 )
2523 {
2524 /* set group key*/
2525 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2526 "%s- %d: setting Broacast key",
2527 __func__, __LINE__);
2528 setKey.keyDirection = eSIR_RX_ONLY;
2529 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2530 }
2531 else
2532 {
2533 /* set pairwise key*/
2534 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2535 "%s- %d: setting pairwise key",
2536 __func__, __LINE__);
2537 setKey.keyDirection = eSIR_TX_RX;
2538 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2539 }
2540
2541 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2542 if( pHostapdState->bssState == BSS_START )
2543 {
2544 status = WLANSAP_SetKeySta( pVosContext, &setKey);
2545
2546 if ( status != eHAL_STATUS_SUCCESS )
2547 {
2548 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2549 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
2550 __LINE__, status );
2551 }
2552 }
2553
2554 /* Saving WEP keys */
2555 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
2556 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
2557 {
2558 //Save the wep key in ap context. Issue setkey after the BSS is started.
2559 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2560 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
2561 }
2562 else
2563 {
2564 //Save the key in ap context. Issue setkey after the BSS is started.
2565 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2566 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
2567 }
2568 }
2569 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2570#ifdef WLAN_FEATURE_P2P
2571 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2572#endif
2573 )
2574 {
2575 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2576 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2577
2578 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
2579
2580 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
2581 params->key, params->key_len);
2582
2583 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
2584
2585 if (!( ( IW_AUTH_KEY_MGMT_802_1X
2586 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2587 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2588 )
2589 &&
2590 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
2591 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
2592 )
2593 )
2594 {
2595 /* in case of static WEP, macaddr/bssid is not coming from nl80211
2596 * interface, copy bssid for pairwise key and group macaddr for
2597 * group key initialization*/
2598
2599 tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
2600
2601 pWextState->roamProfile.negotiatedUCEncryptionType =
2602 pHddStaCtx->conn_info.ucEncryptionType =
2603 ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
2604 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
2605 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
2606
2607
2608 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2609 "%s: Negotiated encryption type %d", __func__,
2610 pWextState->roamProfile.negotiatedUCEncryptionType);
2611
2612 sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
2613 &pWextState->roamProfile, true);
2614 setKey.keyLength = 0;
2615 setKey.keyDirection = eSIR_TX_RX;
2616
2617#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2618 if (pairwise)
2619 {
2620#endif
2621 if (mac_addr)
2622 {
2623 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2624 }
2625 else
2626 {
2627 /* macaddr is NULL, set the peerMac to bssId in case of BSS,
2628 * and peerMacAddress in case of IBSS*/
2629 if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
2630 {
2631 u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
2632 if (HDD_MAX_NUM_IBSS_STA != staidx)
2633 {
2634 vos_mem_copy(setKey.peerMac,
2635 &pHddStaCtx->conn_info.peerMacAddress[staidx],
2636 WNI_CFG_BSSID_LEN);
2637
2638 }
2639 else
2640 {
2641 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
2642 __func__);
2643 return -EOPNOTSUPP;
2644 }
2645 }
2646 else
2647 {
2648 vos_mem_copy(setKey.peerMac,
2649 &pHddStaCtx->conn_info.bssId[0],
2650 WNI_CFG_BSSID_LEN);
2651 }
2652 }
2653#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2654 }
2655 else
2656 {
2657 /* set group key*/
2658 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2659 "%s- %d: setting Group key",
2660 __func__, __LINE__);
2661 setKey.keyDirection = eSIR_RX_ONLY;
2662 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
2663 }
2664#endif
2665 }
2666 else if (
2667#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2668 (!pairwise)
2669#else
2670 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2671#endif
2672 )
2673 {
2674 /* set group key*/
2675 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2676 "%s- %d: setting Group key",
2677 __func__, __LINE__);
2678 setKey.keyDirection = eSIR_RX_ONLY;
2679 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2680 }
2681 else
2682 {
2683 /* set pairwise key*/
2684 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2685 "%s- %d: setting pairwise key",
2686 __func__, __LINE__);
2687 setKey.keyDirection = eSIR_TX_RX;
2688 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2689 }
2690
2691 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2692 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
2693 __func__, setKey.peerMac[0], setKey.peerMac[1],
2694 setKey.peerMac[2], setKey.peerMac[3],
2695 setKey.peerMac[4], setKey.peerMac[5],
2696 setKey.keyDirection);
2697
2698 vos_status = wlan_hdd_check_ula_done(pAdapter);
2699
2700 if ( vos_status != VOS_STATUS_SUCCESS )
2701 {
2702 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2703 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
2704 __LINE__, vos_status );
2705
2706 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2707
2708 return -EINVAL;
2709
2710 }
2711
2712
2713 /* issue set key request to SME*/
2714 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2715 pAdapter->sessionId, &setKey, &roamId );
2716
2717 if ( 0 != status )
2718 {
2719 hddLog(VOS_TRACE_LEVEL_ERROR,
2720 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
2721 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2722 return -EINVAL;
2723 }
2724
2725
2726 /* in case of IBSS as there was no information available about WEP keys during
2727 * IBSS join, group key intialized with NULL key, so re-initialize group key
2728 * with correct value*/
2729 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
2730 !( ( IW_AUTH_KEY_MGMT_802_1X
2731 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2732 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2733 )
2734 &&
2735 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
2736 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
2737 )
2738 )
2739 {
2740 setKey.keyDirection = eSIR_RX_ONLY;
2741 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2742
2743 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2744 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
2745 __func__, setKey.peerMac[0], setKey.peerMac[1],
2746 setKey.peerMac[2], setKey.peerMac[3],
2747 setKey.peerMac[4], setKey.peerMac[5],
2748 setKey.keyDirection);
2749
2750 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2751 pAdapter->sessionId, &setKey, &roamId );
2752
2753 if ( 0 != status )
2754 {
2755 hddLog(VOS_TRACE_LEVEL_ERROR,
2756 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
2757 __func__, status);
2758 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2759 return -EINVAL;
2760 }
2761 }
2762 }
2763
2764 return 0;
2765}
2766
2767/*
2768 * FUNCTION: wlan_hdd_cfg80211_get_key
2769 * This function is used to get the key information
2770 */
2771#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2772static int wlan_hdd_cfg80211_get_key(
2773 struct wiphy *wiphy,
2774 struct net_device *ndev,
2775 u8 key_index, bool pairwise,
2776 const u8 *mac_addr, void *cookie,
2777 void (*callback)(void *cookie, struct key_params*)
2778 )
2779#else
2780static int wlan_hdd_cfg80211_get_key(
2781 struct wiphy *wiphy,
2782 struct net_device *ndev,
2783 u8 key_index, const u8 *mac_addr, void *cookie,
2784 void (*callback)(void *cookie, struct key_params*)
2785 )
2786#endif
2787{
2788 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2789 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2790 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
2791 struct key_params params;
2792
2793 ENTER();
2794
2795 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2796 __func__,pAdapter->device_mode);
2797
2798 memset(&params, 0, sizeof(params));
2799
2800 if (CSR_MAX_NUM_KEY <= key_index)
2801 {
2802 return -EINVAL;
2803 }
2804
2805 switch(pRoamProfile->EncryptionType.encryptionType[0])
2806 {
2807 case eCSR_ENCRYPT_TYPE_NONE:
2808 params.cipher = IW_AUTH_CIPHER_NONE;
2809 break;
2810
2811 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
2812 case eCSR_ENCRYPT_TYPE_WEP40:
2813 params.cipher = WLAN_CIPHER_SUITE_WEP40;
2814 break;
2815
2816 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
2817 case eCSR_ENCRYPT_TYPE_WEP104:
2818 params.cipher = WLAN_CIPHER_SUITE_WEP104;
2819 break;
2820
2821 case eCSR_ENCRYPT_TYPE_TKIP:
2822 params.cipher = WLAN_CIPHER_SUITE_TKIP;
2823 break;
2824
2825 case eCSR_ENCRYPT_TYPE_AES:
2826 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
2827 break;
2828
2829 default:
2830 params.cipher = IW_AUTH_CIPHER_NONE;
2831 break;
2832 }
2833
2834 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
2835 params.seq_len = 0;
2836 params.seq = NULL;
2837 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
2838 callback(cookie, &params);
2839 return 0;
2840}
2841
2842/*
2843 * FUNCTION: wlan_hdd_cfg80211_del_key
2844 * This function is used to delete the key information
2845 */
2846#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2847static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
2848 struct net_device *ndev,
2849 u8 key_index,
2850 bool pairwise,
2851 const u8 *mac_addr
2852 )
2853#else
2854static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
2855 struct net_device *ndev,
2856 u8 key_index,
2857 const u8 *mac_addr
2858 )
2859#endif
2860{
2861 int status = 0;
2862
2863 //This code needs to be revisited. There is sme_removeKey API, we should
2864 //plan to use that. After the change to use correct index in setkey,
2865 //it is observed that this is invalidating peer
2866 //key index whenever re-key is done. This is affecting data link.
2867 //It should be ok to ignore del_key.
2868#if 0
2869 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2870 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2871 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
2872 tCsrRoamSetKey setKey;
2873 v_U32_t roamId= 0xFF;
2874
2875 ENTER();
2876
2877 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
2878 __func__,pAdapter->device_mode);
2879
2880 if (CSR_MAX_NUM_KEY <= key_index)
2881 {
2882 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
2883 key_index);
2884
2885 return -EINVAL;
2886 }
2887
2888 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2889 setKey.keyId = key_index;
2890
2891 if (mac_addr)
2892 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2893 else
2894 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
2895
2896 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
2897
2898 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2899#ifdef WLAN_FEATURE_P2P
2900 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2901#endif
2902 )
2903 {
2904
2905 hdd_hostapd_state_t *pHostapdState =
2906 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2907 if( pHostapdState->bssState == BSS_START)
2908 {
2909 status = WLANSAP_SetKeySta( pVosContext, &setKey);
2910
2911 if ( status != eHAL_STATUS_SUCCESS )
2912 {
2913 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2914 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
2915 __LINE__, status );
2916 }
2917 }
2918 }
2919 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2920#ifdef WLAN_FEATURE_P2P
2921 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2922#endif
2923 )
2924 {
2925 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2926
2927 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
2928
2929 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2930 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
2931 __func__, setKey.peerMac[0], setKey.peerMac[1],
2932 setKey.peerMac[2], setKey.peerMac[3],
2933 setKey.peerMac[4], setKey.peerMac[5]);
2934 if(pAdapter->sessionCtx.station.conn_info.connState ==
2935 eConnectionState_Associated)
2936 {
2937 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2938 pAdapter->sessionId, &setKey, &roamId );
2939
2940 if ( 0 != status )
2941 {
2942 hddLog(VOS_TRACE_LEVEL_ERROR,
2943 "%s: sme_RoamSetKey failure, returned %d",
2944 __func__, status);
2945 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2946 return -EINVAL;
2947 }
2948 }
2949 }
2950#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07002951 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002952 return status;
2953}
2954
2955/*
2956 * FUNCTION: wlan_hdd_cfg80211_set_default_key
2957 * This function is used to set the default tx key index
2958 */
2959#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2960static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
2961 struct net_device *ndev,
2962 u8 key_index,
2963 bool unicast, bool multicast)
2964#else
2965static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
2966 struct net_device *ndev,
2967 u8 key_index)
2968#endif
2969{
2970 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2971 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2972 int status = 0;
2973 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2974
2975 ENTER();
2976
2977 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
2978 __func__,pAdapter->device_mode, key_index);
2979
2980 if (CSR_MAX_NUM_KEY <= key_index)
2981 {
2982 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
2983 key_index);
2984
2985 return -EINVAL;
2986 }
2987
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002988 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2989 {
2990 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2991 "%s:LOGP in Progress. Ignore!!!", __func__);
2992 return -EAGAIN;
2993 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002994
2995 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2996#ifdef WLAN_FEATURE_P2P
2997 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2998#endif
2999 )
3000 {
3001 if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
3002 (eCSR_ENCRYPT_TYPE_TKIP !=
3003 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3004 (eCSR_ENCRYPT_TYPE_AES !=
3005 pWextState->roamProfile.EncryptionType.encryptionType[0])
3006 )
3007 {
3008 /* if default key index is not same as previous one,
3009 * then update the default key index */
3010
3011 tCsrRoamSetKey setKey;
3012 v_U32_t roamId= 0xFF;
3013 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
3014
3015 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
3016 __func__, key_index);
3017
3018 Keys->defaultIndex = (u8)key_index;
3019 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3020 setKey.keyId = key_index;
3021 setKey.keyLength = Keys->KeyLength[key_index];
3022
3023 vos_mem_copy(&setKey.Key[0],
3024 &Keys->KeyMaterial[key_index][0],
3025 Keys->KeyLength[key_index]);
3026
3027 setKey.keyDirection = eSIR_TX_ONLY;
3028
3029 vos_mem_copy(setKey.peerMac,
3030 &pHddStaCtx->conn_info.bssId[0],
3031 WNI_CFG_BSSID_LEN);
3032
3033 setKey.encType =
3034 pWextState->roamProfile.EncryptionType.encryptionType[0];
3035
3036 /* issue set key request */
3037 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3038 pAdapter->sessionId, &setKey, &roamId );
3039
3040 if ( 0 != status )
3041 {
3042 hddLog(VOS_TRACE_LEVEL_ERROR,
3043 "%s: sme_RoamSetKey failed, returned %d", __func__,
3044 status);
3045 return -EINVAL;
3046 }
3047 }
3048 }
3049
3050 /* In SoftAp mode setting key direction for default mode */
3051 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3052 {
3053 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3054 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3055 (eCSR_ENCRYPT_TYPE_AES !=
3056 pWextState->roamProfile.EncryptionType.encryptionType[0])
3057 )
3058 {
3059 /* Saving key direction for default key index to TX default */
3060 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3061 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3062 }
3063 }
3064
3065 return status;
3066}
3067
3068/**
3069 * FUNCTION: wlan_hdd_cfg80211_set_channel
3070 * This function is used to set the channel number
3071 */
3072int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
3073 struct ieee80211_channel *chan,
3074 enum nl80211_channel_type channel_type
3075 )
3076{
3077 v_U32_t num_ch = 0;
3078 u32 channel = 0;
3079 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
3080 int freq = chan->center_freq; /* freq is in MHZ */
3081
3082 ENTER();
3083
3084 hddLog(VOS_TRACE_LEVEL_INFO,
3085 "%s: device_mode = %d freq = %d \n",__func__,
3086 pAdapter->device_mode, chan->center_freq);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07003087 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3088 {
3089 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3090 return -EAGAIN;
3091 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003092
3093 /*
3094 * Do freq to chan conversion
3095 * TODO: for 11a
3096 */
3097
3098 channel = ieee80211_frequency_to_channel(freq);
3099
3100 /* Check freq range */
3101 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
3102 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
3103 {
3104 hddLog(VOS_TRACE_LEVEL_ERROR,
3105 "%s: Channel [%d] is outside valid range from %d to %d\n",
3106 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
3107 WNI_CFG_CURRENT_CHANNEL_STAMAX);
3108 return -EINVAL;
3109 }
3110
3111 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
3112
3113 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode)
3114#ifdef WLAN_FEATURE_P2P
3115 && (WLAN_HDD_P2P_GO != pAdapter->device_mode)
3116#endif
3117 )
3118 {
3119 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
3120 {
3121 hddLog(VOS_TRACE_LEVEL_ERROR,
3122 "%s: Invalid Channel [%d] \n", __func__, channel);
3123 return -EINVAL;
3124 }
3125 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3126 "%s: set channel to [%d] for device mode =%d",
3127 __func__, channel,pAdapter->device_mode);
3128 }
3129 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3130#ifdef WLAN_FEATURE_P2P
3131 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3132#endif
3133 )
3134 {
3135 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3136 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
3137 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3138
3139 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
3140 {
3141 /* Link is up then return cant set channel*/
3142 hddLog( VOS_TRACE_LEVEL_ERROR,
3143 "%s: IBSS Associated, can't set the channel\n", __func__);
3144 return -EINVAL;
3145 }
3146
3147 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
3148 pHddStaCtx->conn_info.operationChannel = channel;
3149 pRoamProfile->ChannelInfo.ChannelList =
3150 &pHddStaCtx->conn_info.operationChannel;
3151 }
3152 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3153#ifdef WLAN_FEATURE_P2P
3154 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
3155#endif
3156 )
3157 {
3158 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
3159
3160 if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3161 {
3162 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3163
3164 /* If auto channel selection is configured as enable/ 1 then ignore
3165 channel set by supplicant
3166 */
3167 if ( cfg_param->apAutoChannelSelection )
3168 {
3169 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = AUTO_CHANNEL_SELECT;
3170
3171 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3172 "%s: set channel to auto channel (0) for device mode =%d",
3173 __func__, pAdapter->device_mode);
3174 }
3175 }
3176 }
3177 else
3178 {
3179 hddLog(VOS_TRACE_LEVEL_FATAL,
3180 "%s: Invalid device mode failed to set valid channel", __func__);
3181 return -EINVAL;
3182 }
3183 EXIT();
3184 return 0;
3185}
3186
3187
3188
3189/*
3190 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3191 * This function is used to inform the BSS details to nl80211 interface.
3192 */
3193static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3194 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3195{
3196 struct net_device *dev = pAdapter->dev;
3197 struct wireless_dev *wdev = dev->ieee80211_ptr;
3198 struct wiphy *wiphy = wdev->wiphy;
3199 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3200 int chan_no;
3201 int ie_length;
3202 const char *ie;
3203 unsigned int freq;
3204 struct ieee80211_channel *chan;
3205 int rssi = 0;
3206 struct cfg80211_bss *bss = NULL;
3207
3208 ENTER();
3209
3210 if( NULL == pBssDesc )
3211 {
3212 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3213 return bss;
3214 }
3215
3216 chan_no = pBssDesc->channelId;
3217 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3218 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3219
3220 if( NULL == ie )
3221 {
3222 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3223 return bss;
3224 }
3225
3226#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3227 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3228 {
3229 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3230 }
3231 else
3232 {
3233 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3234 }
3235#else
3236 freq = ieee80211_channel_to_frequency(chan_no);
3237#endif
3238
3239 chan = __ieee80211_get_channel(wiphy, freq);
3240
3241 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3242 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3243 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3244 if (bss == NULL)
3245 {
3246 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3247
3248 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3249 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3250 pBssDesc->capabilityInfo,
3251 pBssDesc->beaconInterval, ie, ie_length,
3252 rssi, GFP_KERNEL ));
3253}
3254 else
3255 {
3256 return bss;
3257 }
3258}
3259
3260
3261
3262/*
3263 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3264 * This function is used to inform the BSS details to nl80211 interface.
3265 */
3266struct cfg80211_bss*
3267wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3268 tSirBssDescription *bss_desc
3269 )
3270{
3271 /*
3272 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3273 already exists in bss data base of cfg80211 for that particular BSS ID.
3274 Using cfg80211_inform_bss_frame to update the bss entry instead of
3275 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3276 now there is no possibility to get the mgmt(probe response) frame from PE,
3277 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3278 cfg80211_inform_bss_frame.
3279 */
3280 struct net_device *dev = pAdapter->dev;
3281 struct wireless_dev *wdev = dev->ieee80211_ptr;
3282 struct wiphy *wiphy = wdev->wiphy;
3283 int chan_no = bss_desc->channelId;
3284 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
3285 const char *ie =
3286 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3287 unsigned int freq;
3288 struct ieee80211_channel *chan;
3289 struct ieee80211_mgmt *mgmt =
3290 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3291 struct cfg80211_bss *bss_status = NULL;
3292 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3293 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003294#ifdef WLAN_OPEN_SOURCE
3295 struct timespec ts;
3296#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003297
3298 ENTER();
3299
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003300 if (!mgmt)
3301 return NULL;
3302
Jeff Johnson295189b2012-06-20 16:38:30 -07003303 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003304
3305#ifdef WLAN_OPEN_SOURCE
3306 /* Android does not want the timestamp from the frame.
3307 Instead it wants a monotonic increasing value */
3308 get_monotonic_boottime(&ts);
3309 mgmt->u.probe_resp.timestamp =
3310 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3311#else
3312 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003313 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3314 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003315
3316#endif
3317
Jeff Johnson295189b2012-06-20 16:38:30 -07003318 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3319 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
3320 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3321
3322 mgmt->frame_control |=
3323 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3324
3325#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3326 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3327 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3328 {
3329 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3330 }
3331 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3332 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3333
3334 {
3335 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3336 }
3337 else
3338 {
3339 kfree(mgmt);
3340 return NULL;
3341 }
3342#else
3343 freq = ieee80211_channel_to_frequency(chan_no);
3344#endif
3345 chan = __ieee80211_get_channel(wiphy, freq);
3346
3347 /*To keep the rssi icon of the connected AP in the scan window
3348 *and the rssi icon of the wireless networks in sync
3349 * */
3350 if (( eConnectionState_Associated ==
3351 pAdapter->sessionCtx.station.conn_info.connState ) &&
3352 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3353 pAdapter->sessionCtx.station.conn_info.bssId,
3354 WNI_CFG_BSSID_LEN)))
3355 {
3356 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3357 rssi = (pAdapter->rssi * 100);
3358 }
3359 else
3360 {
3361 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3362 }
3363
3364 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3365 frame_len, rssi, GFP_KERNEL);
3366 kfree(mgmt);
3367 return bss_status;
3368}
3369
3370/*
3371 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3372 * This function is used to update the BSS data base of CFG8011
3373 */
3374struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3375 tCsrRoamInfo *pRoamInfo
3376 )
3377{
3378 tCsrRoamConnectedProfile roamProfile;
3379 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3380 struct cfg80211_bss *bss = NULL;
3381
3382 ENTER();
3383
3384 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
3385 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
3386
3387 if (NULL != roamProfile.pBssDesc)
3388 {
3389 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
3390 &roamProfile);
3391
3392 if (NULL == bss)
3393 {
3394 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
3395 __func__);
3396 }
3397
3398 sme_RoamFreeConnectProfile(hHal, &roamProfile);
3399 }
3400 else
3401 {
3402 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
3403 __func__);
3404 }
3405 return bss;
3406}
3407
3408/*
3409 * FUNCTION: wlan_hdd_cfg80211_update_bss
3410 */
3411static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
3412 hdd_adapter_t *pAdapter
3413 )
3414{
3415 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3416 tCsrScanResultInfo *pScanResult;
3417 eHalStatus status = 0;
3418 tScanResultHandle pResult;
3419 struct cfg80211_bss *bss_status = NULL;
3420
3421 ENTER();
3422
3423 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3424 {
3425 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3426 return -EAGAIN;
3427 }
3428
3429 /*
3430 * start getting scan results and populate cgf80211 BSS database
3431 */
3432 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
3433
3434 /* no scan results */
3435 if (NULL == pResult)
3436 {
3437 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
3438 return status;
3439 }
3440
3441 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
3442
3443 while (pScanResult)
3444 {
3445 /*
3446 * cfg80211_inform_bss() is not updating ie field of bss entry, if
3447 * entry already exists in bss data base of cfg80211 for that
3448 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
3449 * bss entry instead of cfg80211_inform_bss, But this call expects
3450 * mgmt packet as input. As of now there is no possibility to get
3451 * the mgmt(probe response) frame from PE, converting bss_desc to
3452 * ieee80211_mgmt(probe response) and passing to c
3453 * fg80211_inform_bss_frame.
3454 * */
3455
3456 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
3457 &pScanResult->BssDescriptor);
3458
3459
3460 if (NULL == bss_status)
3461 {
3462 hddLog(VOS_TRACE_LEVEL_INFO,
3463 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
3464 }
3465 else
3466 {
3467 cfg80211_put_bss(bss_status);
3468 }
3469
3470 pScanResult = sme_ScanResultGetNext(hHal, pResult);
3471 }
3472
3473 sme_ScanResultPurge(hHal, pResult);
3474
3475 return 0;
3476}
3477
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003478void
3479hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
3480{
3481 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003482 "%02X:%02X:%02X:%02X:%02X:%02X\n",
3483 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
3484 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003485} /****** end hddPrintMacAddr() ******/
3486
3487void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003488hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003489{
3490 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003491 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
3492 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
3493 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
3494 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003495} /****** end hddPrintPmkId() ******/
3496
3497//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
3498//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
3499
3500//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
3501//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
3502
3503#define dump_bssid(bssid) \
3504 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003505 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
3506 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
3507 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003508 }
3509
3510#define dump_pmkid(pMac, pmkid) \
3511 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003512 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
3513 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
3514 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003515 }
3516
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07003517#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003518/*
3519 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
3520 * This function is used to notify the supplicant of a new PMKSA candidate.
3521 */
3522int wlan_hdd_cfg80211_pmksa_candidate_notify(
3523 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
3524 int index, bool preauth )
3525{
Jeff Johnsone7245742012-09-05 17:12:55 -07003526#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003527 struct net_device *dev = pAdapter->dev;
3528
3529 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07003530 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003531
3532 if( NULL == pRoamInfo )
3533 {
3534 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
3535 return -EINVAL;
3536 }
3537
3538 dump_bssid(pRoamInfo->bssid);
3539 cfg80211_pmksa_candidate_notify(dev, index,
3540 pRoamInfo->bssid, preauth, GFP_KERNEL);
Jeff Johnsone7245742012-09-05 17:12:55 -07003541#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003542 return 0;
3543}
3544#endif //FEATURE_WLAN_LFR
3545
Jeff Johnson295189b2012-06-20 16:38:30 -07003546/*
3547 * FUNCTION: hdd_cfg80211_scan_done_callback
3548 * scanning callback function, called after finishing scan
3549 *
3550 */
3551static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
3552 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
3553{
3554 struct net_device *dev = (struct net_device *) pContext;
3555 //struct wireless_dev *wdev = dev->ieee80211_ptr;
3556 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003557 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3558 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07003559 struct cfg80211_scan_request *req = NULL;
3560 int ret = 0;
3561
3562 ENTER();
3563
3564 hddLog(VOS_TRACE_LEVEL_INFO,
3565 "%s called with halHandle = %p, pContext = %p,"
3566 "scanID = %d, returned status = %d\n",
3567 __func__, halHandle, pContext, (int) scanId, (int) status);
3568
3569 //Block on scan req completion variable. Can't wait forever though.
3570 ret = wait_for_completion_interruptible_timeout(
3571 &pScanInfo->scan_req_completion_event,
3572 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
3573 if (!ret)
3574 {
3575 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003576 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003577 }
3578
3579 if(pScanInfo->mScanPending != VOS_TRUE)
3580 {
3581 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003582 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003583 }
3584
3585 /* Check the scanId */
3586 if (pScanInfo->scanId != scanId)
3587 {
3588 hddLog(VOS_TRACE_LEVEL_INFO,
3589 "%s called with mismatched scanId pScanInfo->scanId = %d "
3590 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
3591 (int) scanId);
3592 }
3593
Jeff Johnson295189b2012-06-20 16:38:30 -07003594 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
3595 pAdapter);
3596
3597 if (0 > ret)
3598 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
3599
3600
3601 /* If any client wait scan result through WEXT
3602 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003603 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07003604 {
3605 /* The other scan request waiting for current scan finish
3606 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003607 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003608 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003609 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003610 }
3611 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003612 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003613 {
3614 struct net_device *dev = pAdapter->dev;
3615 union iwreq_data wrqu;
3616 int we_event;
3617 char *msg;
3618
3619 memset(&wrqu, '\0', sizeof(wrqu));
3620 we_event = SIOCGIWSCAN;
3621 msg = NULL;
3622 wireless_send_event(dev, we_event, &wrqu, msg);
3623 }
3624 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003625 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003626
3627 /* Get the Scan Req */
3628 req = pAdapter->request;
3629
3630 if (!req)
3631 {
3632 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003633 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07003634 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003635 }
3636
3637 /*
3638 * setting up 0, just in case.
3639 */
3640 req->n_ssids = 0;
3641 req->n_channels = 0;
3642 req->ie = 0;
3643
Jeff Johnson295189b2012-06-20 16:38:30 -07003644 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003645 /* Scan is no longer pending */
3646 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003647
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07003648 /*
3649 * cfg80211_scan_done informing NL80211 about completion
3650 * of scanning
3651 */
3652 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudi070e8702012-10-24 14:31:17 -07003653 complete(&pAdapter->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003654#ifdef WLAN_FEATURE_P2P
3655 /* Flush out scan result after p2p_serach is done */
Jeff Johnsone7245742012-09-05 17:12:55 -07003656 if(pScanInfo->flushP2pScanResults)
Jeff Johnson295189b2012-06-20 16:38:30 -07003657 {
3658 tANI_U8 sessionId = pAdapter->sessionId;
Madan Mohan Koyyalamudiab41d0f2012-10-31 17:17:10 -07003659 sme_ScanFlushP2PResult(WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId);
Jeff Johnsone7245742012-09-05 17:12:55 -07003660 pScanInfo->flushP2pScanResults = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003661 }
3662#endif
3663
Jeff Johnsone7245742012-09-05 17:12:55 -07003664allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003665 /* release the wake lock at the end of the scan*/
3666 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07003667
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003668 /* Acquire wakelock to handle the case where APP's tries to suspend
3669 * immediatly after the driver gets connect request(i.e after scan)
3670 * from supplicant, this result in app's is suspending and not able
3671 * to process the connect request to AP */
3672 hdd_allow_suspend_timeout(100);
3673
Jeff Johnson295189b2012-06-20 16:38:30 -07003674 EXIT();
3675 return 0;
3676}
3677
3678/*
3679 * FUNCTION: wlan_hdd_cfg80211_scan
3680 * this scan respond to scan trigger and update cfg80211 scan database
3681 * later, scan dump command can be used to recieve scan results
3682 */
3683int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, struct net_device *dev,
3684 struct cfg80211_scan_request *request)
3685{
3686 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
3687 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3688 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3689 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3690 tCsrScanRequest scanRequest;
3691 tANI_U8 *channelList = NULL, i;
3692 v_U32_t scanId = 0;
3693 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003694 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07003695#ifdef WLAN_FEATURE_P2P
3696 v_U8_t* pP2pIe = NULL;
3697#endif
3698
3699 ENTER();
3700
3701 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3702 __func__,pAdapter->device_mode);
3703#ifdef WLAN_BTAMP_FEATURE
3704 //Scan not supported when AMP traffic is on.
3705 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
3706 {
3707 hddLog(VOS_TRACE_LEVEL_ERROR,
3708 "%s: No scanning when AMP is on", __func__);
3709 return -EOPNOTSUPP;
3710 }
3711#endif
3712 //Scan on any other interface is not supported.
3713 if( pAdapter->device_mode == WLAN_HDD_SOFTAP )
3714 {
3715 hddLog(VOS_TRACE_LEVEL_ERROR,
3716 "%s: Not scanning on device_mode = %d",
3717 __func__, pAdapter->device_mode);
3718 return -EOPNOTSUPP;
3719 }
3720
3721 if (TRUE == pScanInfo->mScanPending)
3722 {
3723 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
3724 return -EBUSY;
3725 }
3726
3727 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3728 {
3729 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3730 "%s:LOGP in Progress. Ignore!!!", __func__);
3731 return -EAGAIN;
3732 }
3733
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07003734 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
3735 {
3736 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3737 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
3738 return -EAGAIN;
3739 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07003740 //Don't Allow Scan and return busy if Remain On
3741 //Channel and action frame is pending
3742 //Otherwise Cancel Remain On Channel and allow Scan
3743 //If no action frame pending
3744 if(0 != wlan_hdd_check_remain_on_channel(pAdapter))
3745 {
3746 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
3747 return -EBUSY;
3748 }
3749
Jeff Johnson295189b2012-06-20 16:38:30 -07003750 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
3751 {
3752 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
3753 "%s: Aquire lock fail", __func__);
3754 return -EAGAIN;
3755 }
3756 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
3757 {
3758 hddLog(VOS_TRACE_LEVEL_WARN,
3759 "%s: MAX TM Level Scan not allowed", __func__);
3760 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
3761 return -EBUSY;
3762 }
3763 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
3764
3765 vos_mem_zero( &scanRequest, sizeof(scanRequest));
3766
3767 if (NULL != request)
3768 {
3769 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
3770 (int)request->n_ssids);
3771
3772 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
3773 * Becasue of this, driver is assuming that this is not wildcard scan and so
3774 * is not aging out the scan results.
3775 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07003776 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07003777 {
3778 request->n_ssids = 0;
3779 }
3780
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003781 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07003782 {
3783 tCsrSSIDInfo *SsidInfo;
3784 int j;
3785 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
3786 /* Allocate num_ssid tCsrSSIDInfo structure */
3787 SsidInfo = scanRequest.SSIDs.SSIDList =
3788 ( tCsrSSIDInfo *)vos_mem_malloc(
3789 request->n_ssids*sizeof(tCsrSSIDInfo));
3790
3791 if(NULL == scanRequest.SSIDs.SSIDList)
3792 {
3793 hddLog(VOS_TRACE_LEVEL_ERROR,
3794 "memory alloc failed SSIDInfo buffer");
3795 return -ENOMEM;
3796 }
3797
3798 /* copy all the ssid's and their length */
3799 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
3800 {
3801 /* get the ssid length */
3802 SsidInfo->SSID.length = request->ssids[j].ssid_len;
3803 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
3804 SsidInfo->SSID.length);
3805 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
3806 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
3807 j, SsidInfo->SSID.ssId);
3808 }
3809 /* set the scan type to active */
3810 scanRequest.scanType = eSIR_ACTIVE_SCAN;
3811 }
3812 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
3813 {
3814 /* set the scan type to active */
3815 scanRequest.scanType = eSIR_ACTIVE_SCAN;
3816 }
3817 else
3818 {
3819 /*Set the scan type to default type, in this case it is ACTIVE*/
3820 scanRequest.scanType = pScanInfo->scan_mode;
3821 }
3822 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
3823 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
3824 }
3825 else
3826 {
3827 /* set the scan type to active */
3828 scanRequest.scanType = eSIR_ACTIVE_SCAN;
3829 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
3830
3831 /* set min and max channel time to zero */
3832 scanRequest.minChnTime = 0;
3833 scanRequest.maxChnTime = 0;
3834 }
3835
3836 /* set BSSType to default type */
3837 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
3838
3839 /*TODO: scan the requested channels only*/
3840
3841 /*Right now scanning all the channels */
3842 if( request )
3843 {
3844 if( request->n_channels )
3845 {
3846 channelList = vos_mem_malloc( request->n_channels );
3847 if( NULL == channelList )
3848 {
3849 status = -ENOMEM;
3850 goto free_mem;
3851 }
3852
3853 for( i = 0 ; i < request->n_channels ; i++ )
3854 channelList[i] = request->channels[i]->hw_value;
3855 }
3856
3857 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
3858 scanRequest.ChannelInfo.ChannelList = channelList;
3859
3860 /* set requestType to full scan */
3861 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
3862
3863 if( request->ie_len )
3864 {
3865 /* save this for future association (join requires this) */
3866 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
3867 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
3868 pScanInfo->scanAddIE.length = request->ie_len;
3869
3870 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07003871 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
3872 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07003873 )
3874 {
3875 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
3876 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
3877 }
3878
3879 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
3880 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
3881
3882#ifdef WLAN_FEATURE_P2P
3883 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
3884 request->ie_len);
3885 if (pP2pIe != NULL)
3886 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07003887#ifdef WLAN_FEATURE_P2P_DEBUG
3888 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
3889 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
3890 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
3891 {
3892 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
3893 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
3894 "Go nego completed to Connection is started");
3895 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
3896 "for 8way Handshake");
3897 }
3898 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
3899 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
3900 {
3901 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
3902 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
3903 "Disconnected state to Connection is started");
3904 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
3905 "for 4way Handshake");
3906 }
3907#endif
3908
Jeff Johnsone7245742012-09-05 17:12:55 -07003909 /* no_cck will be set during p2p find to disable 11b rates */
3910 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07003911 {
3912 tANI_U8 sessionId = pAdapter->sessionId;
3913 hddLog(VOS_TRACE_LEVEL_INFO,
3914 "%s: This is a P2P Search", __func__);
3915 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07003916
3917 /* Flush the scan results only for P2P search.
3918 P2P search happens on 3 social channels (1, 6, 11) */
3919 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
3920 {
3921 pScanInfo->flushP2pScanResults = 1;
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07003922 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnsone7245742012-09-05 17:12:55 -07003923 sessionId );
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07003924 /* set requestType to P2P Discovery */
3925 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07003926 }
3927
3928 /*
3929 Skip Dfs Channel in case of P2P Search
3930 if it is set in ini file
3931 */
3932 if(cfg_param->skipDfsChnlInP2pSearch)
3933 {
3934 scanRequest.skipDfsChnlInP2pSearch = 1;
3935 }
3936 else
3937 {
3938 scanRequest.skipDfsChnlInP2pSearch = 0;
3939 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003940
Jeff Johnson295189b2012-06-20 16:38:30 -07003941 }
3942 }
3943#endif
3944 }
3945 }
3946
3947 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
3948
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003949 /* acquire the wakelock to avoid the apps suspend during the scan. To
3950 * address the following issues.
3951 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
3952 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
3953 * for long time, this result in apps running at full power for long time.
3954 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
3955 * be stuck in full power because of resume BMPS
3956 */
3957 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07003958
3959 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07003960 pAdapter->sessionId, &scanRequest, &scanId,
3961 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07003962
Jeff Johnson295189b2012-06-20 16:38:30 -07003963 if (eHAL_STATUS_SUCCESS != status)
3964 {
3965 hddLog(VOS_TRACE_LEVEL_ERROR,
3966 "%s: sme_ScanRequest returned error %d", __func__, status);
3967 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07003968 if(eHAL_STATUS_RESOURCES == status)
3969 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07003970 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 -07003971 status = -EBUSY;
3972 } else {
3973 status = -EIO;
3974 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003975 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07003976 goto free_mem;
3977 }
3978
3979 pScanInfo->mScanPending = TRUE;
3980 pAdapter->request = request;
3981 pScanInfo->scanId = scanId;
3982
3983 complete(&pScanInfo->scan_req_completion_event);
3984
3985free_mem:
3986 if( scanRequest.SSIDs.SSIDList )
3987 {
3988 vos_mem_free(scanRequest.SSIDs.SSIDList);
3989 }
3990
3991 if( channelList )
3992 vos_mem_free( channelList );
3993
3994 EXIT();
3995
3996 return status;
3997}
3998
3999/*
4000 * FUNCTION: wlan_hdd_cfg80211_connect_start
4001 * This function is used to start the association process
4002 */
4003int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004004 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004005{
4006 int status = 0;
4007 hdd_wext_state_t *pWextState;
4008 v_U32_t roamId;
4009 tCsrRoamProfile *pRoamProfile;
4010 eMib_dot11DesiredBssType connectedBssType;
4011 eCsrAuthType RSNAuthType;
4012
4013 ENTER();
4014
4015 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4016
4017 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4018 {
4019 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4020 return -EINVAL;
4021 }
4022
4023 pRoamProfile = &pWextState->roamProfile;
4024
4025 if (pRoamProfile)
4026 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004027 int ret = 0;
4028 hdd_station_ctx_t *pHddStaCtx;
4029 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4030 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4031
4032 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4033 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4034 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004035 {
4036 /* Issue disconnect to CSR */
4037 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4038 if( eHAL_STATUS_SUCCESS ==
4039 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4040 pAdapter->sessionId,
4041 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4042 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004043 ret = wait_for_completion_interruptible_timeout(
4044 &pAdapter->disconnect_comp_var,
4045 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4046 if (0 == ret)
4047 {
4048 VOS_ASSERT(0);
4049 }
4050 }
4051 }
4052 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4053 {
4054 ret = wait_for_completion_interruptible_timeout(
4055 &pAdapter->disconnect_comp_var,
4056 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4057 if (0 == ret)
4058 {
4059 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004060 }
4061 }
4062
4063 if (HDD_WMM_USER_MODE_NO_QOS ==
4064 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4065 {
4066 /*QoS not enabled in cfg file*/
4067 pRoamProfile->uapsd_mask = 0;
4068 }
4069 else
4070 {
4071 /*QoS enabled, update uapsd mask from cfg file*/
4072 pRoamProfile->uapsd_mask =
4073 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4074 }
4075
4076 pRoamProfile->SSIDs.numOfSSIDs = 1;
4077 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4078 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
4079 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
4080 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4081 ssid, ssid_len);
4082
4083 if (bssid)
4084 {
4085 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4086 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4087 WNI_CFG_BSSID_LEN);
4088 /* Save BSSID in seperate variable as well, as RoamProfile
4089 BSSID is getting zeroed out in the association process. And in
4090 case of join failure we should send valid BSSID to supplicant
4091 */
4092 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4093 WNI_CFG_BSSID_LEN);
4094 }
4095
4096 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4097 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4098 {
4099 /*set gen ie*/
4100 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4101 /*set auth*/
4102 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4103 }
4104 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4105 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4106 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4107 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4108 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4109 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4110 )
4111 {
4112 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4113 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4114 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4115 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4116 eCSR_AUTH_TYPE_AUTOSWITCH;
4117 pWextState->roamProfile.AuthType.authType[0] =
4118 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4119 }
4120#ifdef FEATURE_WLAN_WAPI
4121 if (pAdapter->wapi_info.nWapiMode)
4122 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004123 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004124 switch (pAdapter->wapi_info.wapiAuthMode)
4125 {
4126 case WAPI_AUTH_MODE_PSK:
4127 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004128 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004129 pAdapter->wapi_info.wapiAuthMode);
4130 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4131 break;
4132 }
4133 case WAPI_AUTH_MODE_CERT:
4134 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004135 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004136 pAdapter->wapi_info.wapiAuthMode);
4137 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4138 break;
4139 }
4140 } // End of switch
4141 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4142 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4143 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004144 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004145 pRoamProfile->AuthType.numEntries = 1;
4146 pRoamProfile->EncryptionType.numEntries = 1;
4147 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4148 pRoamProfile->mcEncryptionType.numEntries = 1;
4149 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4150 }
4151 }
4152#endif /* FEATURE_WLAN_WAPI */
4153 pRoamProfile->csrPersona = pAdapter->device_mode;
4154
Jeff Johnson32d95a32012-09-10 13:15:23 -07004155 if( operatingChannel )
4156 {
4157 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4158 pRoamProfile->ChannelInfo.numOfChannels = 1;
4159 }
4160
Jeff Johnson295189b2012-06-20 16:38:30 -07004161 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4162 pAdapter->sessionId, pRoamProfile, &roamId);
4163
Jeff Johnson32d95a32012-09-10 13:15:23 -07004164 pRoamProfile->ChannelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004165 pRoamProfile->ChannelInfo.numOfChannels = 0;
4166 }
4167 else
4168 {
4169 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4170 return -EINVAL;
4171 }
4172 EXIT();
4173 return status;
4174}
4175
4176/*
4177 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4178 * This function is used to set the authentication type (OPEN/SHARED).
4179 *
4180 */
4181static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4182 enum nl80211_auth_type auth_type)
4183{
4184 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4185 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4186
4187 ENTER();
4188
4189 /*set authentication type*/
4190 switch (auth_type)
4191 {
4192 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4193 case NL80211_AUTHTYPE_AUTOMATIC:
4194 hddLog(VOS_TRACE_LEVEL_INFO,
4195 "%s: set authentication type to OPEN", __func__);
4196 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4197 break;
4198
4199 case NL80211_AUTHTYPE_SHARED_KEY:
4200 hddLog(VOS_TRACE_LEVEL_INFO,
4201 "%s: set authentication type to SHARED", __func__);
4202 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4203 break;
4204#ifdef FEATURE_WLAN_CCX
4205 case NL80211_AUTHTYPE_NETWORK_EAP:
4206 hddLog(VOS_TRACE_LEVEL_INFO,
4207 "%s: set authentication type to CCKM WPA", __func__);
4208 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4209 break;
4210#endif
4211
4212
4213 default:
4214 hddLog(VOS_TRACE_LEVEL_ERROR,
4215 "%s: Unsupported authentication type %d", __func__,
4216 auth_type);
4217 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4218 return -EINVAL;
4219 }
4220
4221 pWextState->roamProfile.AuthType.authType[0] =
4222 pHddStaCtx->conn_info.authType;
4223 return 0;
4224}
4225
4226/*
4227 * FUNCTION: wlan_hdd_set_akm_suite
4228 * This function is used to set the key mgmt type(PSK/8021x).
4229 *
4230 */
4231static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
4232 u32 key_mgmt
4233 )
4234{
4235 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4236 ENTER();
4237
4238 /*set key mgmt type*/
4239 switch(key_mgmt)
4240 {
4241 case WLAN_AKM_SUITE_PSK:
4242 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
4243 __func__);
4244 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
4245 break;
4246
4247 case WLAN_AKM_SUITE_8021X:
4248 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
4249 __func__);
4250 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
4251 break;
4252#ifdef FEATURE_WLAN_CCX
4253#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
4254#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
4255 case WLAN_AKM_SUITE_CCKM:
4256 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
4257 __func__);
4258 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
4259 break;
4260#endif
4261
4262 default:
4263 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
4264 __func__, key_mgmt);
4265 return -EINVAL;
4266
4267 }
4268 return 0;
4269}
4270
4271/*
4272 * FUNCTION: wlan_hdd_cfg80211_set_cipher
4273 * This function is used to set the encryption type
4274 * (NONE/WEP40/WEP104/TKIP/CCMP).
4275 */
4276static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
4277 u32 cipher,
4278 bool ucast
4279 )
4280{
4281 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4282 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4283 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4284
4285 ENTER();
4286
4287 if (!cipher)
4288 {
4289 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
4290 __func__, cipher);
4291 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4292 }
4293 else
4294 {
4295
4296 /*set encryption method*/
4297 switch (cipher)
4298 {
4299 case IW_AUTH_CIPHER_NONE:
4300 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4301 break;
4302
4303 case WLAN_CIPHER_SUITE_WEP40:
4304 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4305 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4306 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
4307 else
4308 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4309 break;
4310
4311 case WLAN_CIPHER_SUITE_WEP104:
4312 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4313 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4314 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
4315 else
4316 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
4317 break;
4318
4319 case WLAN_CIPHER_SUITE_TKIP:
4320 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
4321 break;
4322
4323 case WLAN_CIPHER_SUITE_CCMP:
4324 encryptionType = eCSR_ENCRYPT_TYPE_AES;
4325 break;
4326#ifdef FEATURE_WLAN_WAPI
4327 case WLAN_CIPHER_SUITE_SMS4:
4328 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
4329 break;
4330#endif
4331
4332#ifdef FEATURE_WLAN_CCX
4333 case WLAN_CIPHER_SUITE_KRK:
4334 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
4335 break;
4336#endif
4337 default:
4338 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
4339 __func__, cipher);
4340 return -EOPNOTSUPP;
4341 }
4342 }
4343
4344 if (ucast)
4345 {
4346 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
4347 __func__, encryptionType);
4348 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
4349 pWextState->roamProfile.EncryptionType.numEntries = 1;
4350 pWextState->roamProfile.EncryptionType.encryptionType[0] =
4351 encryptionType;
4352 }
4353 else
4354 {
4355 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
4356 __func__, encryptionType);
4357 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
4358 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
4359 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
4360 }
4361
4362 return 0;
4363}
4364
4365
4366/*
4367 * FUNCTION: wlan_hdd_cfg80211_set_ie
4368 * This function is used to parse WPA/RSN IE's.
4369 */
4370int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
4371 u8 *ie,
4372 size_t ie_len
4373 )
4374{
4375 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4376 u8 *genie = ie;
4377 v_U16_t remLen = ie_len;
4378#ifdef FEATURE_WLAN_WAPI
4379 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
4380 u16 *tmp;
4381 v_U16_t akmsuiteCount;
4382 int *akmlist;
4383#endif
4384 ENTER();
4385
4386 /* clear previous assocAddIE */
4387 pWextState->assocAddIE.length = 0;
4388 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
4389
4390 while (remLen >= 2)
4391 {
4392 v_U16_t eLen = 0;
4393 v_U8_t elementId;
4394 elementId = *genie++;
4395 eLen = *genie++;
4396 remLen -= 2;
4397
4398 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
4399 __func__, elementId, eLen);
4400
4401 switch ( elementId )
4402 {
4403 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004404 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 -07004405 {
4406 hddLog(VOS_TRACE_LEVEL_ERROR,
4407 "%s: Invalid WPA IE", __func__);
4408 return -EINVAL;
4409 }
4410 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
4411 {
4412 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4413 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
4414 __func__, eLen + 2);
4415
4416 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4417 {
4418 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE. "
4419 "Need bigger buffer space\n");
4420 VOS_ASSERT(0);
4421 return -ENOMEM;
4422 }
4423 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4424 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4425 pWextState->assocAddIE.length += eLen + 2;
4426
4427 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
4428 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4429 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4430 }
4431 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
4432 {
4433 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
4434 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4435 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
4436 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
4437 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
4438 }
4439#ifdef WLAN_FEATURE_P2P
4440 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
4441 P2P_OUI_TYPE_SIZE))
4442 /*Consider P2P IE, only for P2P Client */
4443 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4444 {
4445 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4446 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
4447 __func__, eLen + 2);
4448
4449 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4450 {
4451 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
4452 "Need bigger buffer space\n");
4453 VOS_ASSERT(0);
4454 return -ENOMEM;
4455 }
4456 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4457 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4458 pWextState->assocAddIE.length += eLen + 2;
4459
4460 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4461 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4462 }
4463#endif
4464#ifdef WLAN_FEATURE_WFD
4465 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
4466 WFD_OUI_TYPE_SIZE))
4467 /*Consider WFD IE, only for P2P Client */
4468 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4469 {
4470 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4471 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
4472 __func__, eLen + 2);
4473
4474 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4475 {
4476 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
4477 "Need bigger buffer space\n");
4478 VOS_ASSERT(0);
4479 return -ENOMEM;
4480 }
4481 // WFD IE is saved to Additional IE ; it should be accumulated to handle
4482 // WPS IE + P2P IE + WFD IE
4483 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4484 pWextState->assocAddIE.length += eLen + 2;
4485
4486 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4487 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4488 }
4489#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004490 /* Appending HS 2.0 Indication Element in Assiciation Request */
4491 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004492 HS20_OUI_TYPE_SIZE)) )
4493 {
4494 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4495 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
4496 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004497
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004498 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4499 {
4500 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
4501 "Need bigger buffer space\n");
4502 VOS_ASSERT(0);
4503 return -ENOMEM;
4504 }
4505 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4506 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004507
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004508 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4509 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4510 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004511
Jeff Johnson295189b2012-06-20 16:38:30 -07004512 break;
4513 case DOT11F_EID_RSN:
4514 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
4515 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4516 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
4517 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
4518 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
4519 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004520 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
4521 case DOT11F_EID_EXTCAP:
4522 {
4523 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4524 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
4525 __func__, eLen + 2);
4526
4527 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4528 {
4529 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
4530 "Need bigger buffer space\n");
4531 VOS_ASSERT(0);
4532 return -ENOMEM;
4533 }
4534 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4535 pWextState->assocAddIE.length += eLen + 2;
4536
4537 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4538 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4539 break;
4540 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004541#ifdef FEATURE_WLAN_WAPI
4542 case WLAN_EID_WAPI:
4543 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
4544 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
4545 pAdapter->wapi_info.nWapiMode);
4546 tmp = (u16 *)ie;
4547 tmp = tmp + 2; // Skip element Id and Len, Version
4548 akmsuiteCount = WPA_GET_LE16(tmp);
4549 tmp = tmp + 1;
4550 akmlist = (int *)(tmp);
4551 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
4552 {
4553 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
4554 }
4555 else
4556 {
4557 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
4558 VOS_ASSERT(0);
4559 return -EINVAL;
4560 }
4561
4562 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
4563 {
4564 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004565 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004566 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
4567 }
4568 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
4569 {
4570 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004571 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004572 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
4573 }
4574 break;
4575#endif
4576 default:
4577 hddLog (VOS_TRACE_LEVEL_ERROR,
4578 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004579 /* when Unknown IE is received we should break and continue
4580 * to the next IE in the buffer instead we were returning
4581 * so changing this to break */
4582 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07004583 }
4584 genie += eLen;
4585 remLen -= eLen;
4586 }
4587 EXIT();
4588 return 0;
4589}
4590
4591/*
4592 * FUNCTION: wlan_hdd_cfg80211_set_privacy
4593 * This function is used to initialize the security
4594 * parameters during connect operation.
4595 */
4596int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
4597 struct cfg80211_connect_params *req
4598 )
4599{
4600 int status = 0;
4601 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4602 ENTER();
4603
4604 /*set wpa version*/
4605 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
4606
4607 if (req->crypto.wpa_versions)
4608 {
4609 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
4610 && ( (req->ie_len)
4611 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
4612 // Make sure that it is including a WPA IE.
4613 /* Currently NL is putting WPA version 1 even for open,
4614 * since p2p ie is also put in same buffer.
4615 * */
4616 {
4617 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
4618 }
4619 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
4620 {
4621 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
4622 }
4623 }
4624
4625 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
4626 pWextState->wpaVersion);
4627
4628 /*set authentication type*/
4629 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
4630
4631 if (0 > status)
4632 {
4633 hddLog(VOS_TRACE_LEVEL_ERROR,
4634 "%s: failed to set authentication type ", __func__);
4635 return status;
4636 }
4637
4638 /*set key mgmt type*/
4639 if (req->crypto.n_akm_suites)
4640 {
4641 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
4642 if (0 > status)
4643 {
4644 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
4645 __func__);
4646 return status;
4647 }
4648 }
4649
4650 /*set pairwise cipher type*/
4651 if (req->crypto.n_ciphers_pairwise)
4652 {
4653 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
4654 req->crypto.ciphers_pairwise[0], true);
4655 if (0 > status)
4656 {
4657 hddLog(VOS_TRACE_LEVEL_ERROR,
4658 "%s: failed to set unicast cipher type", __func__);
4659 return status;
4660 }
4661 }
4662 else
4663 {
4664 /*Reset previous cipher suite to none*/
4665 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
4666 if (0 > status)
4667 {
4668 hddLog(VOS_TRACE_LEVEL_ERROR,
4669 "%s: failed to set unicast cipher type", __func__);
4670 return status;
4671 }
4672 }
4673
4674 /*set group cipher type*/
4675 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
4676 false);
4677
4678 if (0 > status)
4679 {
4680 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
4681 __func__);
4682 return status;
4683 }
4684
4685 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
4686 if (req->ie_len)
4687 {
4688 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
4689 if ( 0 > status)
4690 {
4691 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
4692 __func__);
4693 return status;
4694 }
4695 }
4696
4697 /*incase of WEP set default key information*/
4698 if (req->key && req->key_len)
4699 {
4700 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
4701 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
4702 )
4703 {
4704 if ( IW_AUTH_KEY_MGMT_802_1X
4705 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
4706 {
4707 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
4708 __func__);
4709 return -EOPNOTSUPP;
4710 }
4711 else
4712 {
4713 u8 key_len = req->key_len;
4714 u8 key_idx = req->key_idx;
4715
4716 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
4717 && (CSR_MAX_NUM_KEY > key_idx)
4718 )
4719 {
4720 hddLog(VOS_TRACE_LEVEL_INFO,
4721 "%s: setting default wep key, key_idx = %hu key_len %hu",
4722 __func__, key_idx, key_len);
4723 vos_mem_copy(
4724 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
4725 req->key, key_len);
4726 pWextState->roamProfile.Keys.KeyLength[key_idx] =
4727 (u8)key_len;
4728 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
4729 }
4730 }
4731 }
4732 }
4733
4734 return status;
4735}
4736
4737/*
4738 * FUNCTION: wlan_hdd_cfg80211_set_privacy
4739 * This function is used to initialize the security
4740 * parameters during connect operation.
4741 */
4742static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
4743 struct net_device *ndev,
4744 struct cfg80211_connect_params *req
4745 )
4746{
4747 int status = 0;
4748 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
4749 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
4750 hdd_context_t *pHddCtx = NULL;
4751
4752 ENTER();
4753
4754 hddLog(VOS_TRACE_LEVEL_INFO,
4755 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
4756
4757 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
4758 {
4759 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4760 "%s:LOGP in Progress. Ignore!!!", __func__);
4761 return -EAGAIN;
4762 }
4763
4764#ifdef WLAN_BTAMP_FEATURE
4765 //Infra connect not supported when AMP traffic is on.
4766 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
4767 {
4768 hddLog(VOS_TRACE_LEVEL_ERROR,
4769 "%s: No connection when AMP is on", __func__);
4770 return -1;
4771 }
4772#endif
4773 /*initialise security parameters*/
4774 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
4775
4776 if ( 0 > status)
4777 {
4778 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
4779 __func__);
4780 return status;
4781 }
4782
4783 //If Device Mode is Station Concurrent Sessions Exit BMps
4784 //P2P Mode will be taken care in Open/close adaptor
4785 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
4786 (vos_concurrent_sessions_running()))
4787 {
4788 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
4789
4790 if (NULL != pVosContext)
4791 {
4792 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
4793 if(NULL != pHddCtx)
4794 {
4795 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
4796 }
4797 }
4798 }
4799
Mohit Khanna765234a2012-09-11 15:08:35 -07004800 if ( req->channel )
4801 {
4802 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
4803 req->ssid_len, req->bssid,
4804 req->channel->hw_value);
4805 }
4806 else
4807 {
4808 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
4809 req->ssid_len, req->bssid,
4810 0);
4811 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004812
4813 if (0 > status)
4814 {
4815 //ReEnable BMPS if disabled
4816 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
4817 (NULL != pHddCtx))
4818 {
4819 //ReEnable Bmps and Imps back
4820 hdd_enable_bmps_imps(pHddCtx);
4821 }
4822
4823 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
4824 return status;
4825 }
4826 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
4827 EXIT();
4828 return status;
4829}
4830
4831
4832/*
4833 * FUNCTION: wlan_hdd_cfg80211_disconnect
4834 * This function is used to issue a disconnect request to SME
4835 */
4836static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
4837 struct net_device *dev,
4838 u16 reason
4839 )
4840{
4841 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4842 tCsrRoamProfile *pRoamProfile =
4843 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
4844 int status = 0;
4845 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4846
4847 ENTER();
4848
4849 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4850 __func__,pAdapter->device_mode);
4851
4852 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
4853 __func__, reason);
4854
4855 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4856 {
4857 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4858 "%s:LOGP in Progress. Ignore!!!",__func__);
4859 return -EAGAIN;
4860 }
4861 if (NULL != pRoamProfile)
4862 {
4863 /*issue disconnect request to SME, if station is in connected state*/
4864 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
4865 {
4866 eCsrRoamDisconnectReason reasonCode =
4867 eCSR_DISCONNECT_REASON_UNSPECIFIED;
4868 switch(reason)
4869 {
4870 case WLAN_REASON_MIC_FAILURE:
4871 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
4872 break;
4873
4874 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
4875 case WLAN_REASON_DISASSOC_AP_BUSY:
4876 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
4877 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
4878 break;
4879
4880 case WLAN_REASON_PREV_AUTH_NOT_VALID:
4881 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
4882 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
4883 break;
4884
4885 case WLAN_REASON_DEAUTH_LEAVING:
4886 default:
4887 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
4888 break;
4889 }
4890 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4891 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
4892 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4893
4894 /*issue disconnect*/
4895 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4896 pAdapter->sessionId, reasonCode);
4897
4898 if ( 0 != status)
4899 {
4900 hddLog(VOS_TRACE_LEVEL_ERROR,
4901 "%s csrRoamDisconnect failure, returned %d \n",
4902 __func__, (int)status );
4903 return -EINVAL;
4904 }
4905
4906 wait_for_completion_interruptible_timeout(
4907 &pAdapter->disconnect_comp_var,
4908 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4909
4910
4911 /*stop tx queues*/
4912 netif_tx_disable(dev);
4913 netif_carrier_off(dev);
4914 }
4915 }
4916 else
4917 {
4918 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
4919 }
4920
4921 return status;
4922}
4923
4924/*
4925 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
4926 * This function is used to initialize the security
4927 * settings in IBSS mode.
4928 */
4929static int wlan_hdd_cfg80211_set_privacy_ibss(
4930 hdd_adapter_t *pAdapter,
4931 struct cfg80211_ibss_params *params
4932 )
4933{
4934 int status = 0;
4935 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4936 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4937 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4938
4939 ENTER();
4940
4941 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
4942
4943 if (params->ie_len && ( NULL != params->ie) )
4944 {
4945 if (WLAN_EID_RSN == params->ie[0])
4946 {
4947 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
4948 encryptionType = eCSR_ENCRYPT_TYPE_AES;
4949 }
4950 else
4951 {
4952 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
4953 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
4954 }
4955 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
4956
4957 if (0 > status)
4958 {
4959 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
4960 __func__);
4961 return status;
4962 }
4963 }
4964
4965 pWextState->roamProfile.AuthType.authType[0] =
4966 pHddStaCtx->conn_info.authType =
4967 eCSR_AUTH_TYPE_OPEN_SYSTEM;
4968
4969 if (params->privacy)
4970 {
4971 /* Security enabled IBSS, At this time there is no information available
4972 * about the security paramters, so initialise the encryption type to
4973 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
4974 * The correct security parameters will be updated later in
4975 * wlan_hdd_cfg80211_add_key */
4976 /* Hal expects encryption type to be set inorder
4977 *enable privacy bit in beacons */
4978
4979 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4980 }
4981
4982 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
4983 pWextState->roamProfile.EncryptionType.numEntries = 1;
4984 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
4985
4986 return status;
4987}
4988
4989/*
4990 * FUNCTION: wlan_hdd_cfg80211_join_ibss
4991 * This function is used to create/join an IBSS
4992 */
4993static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
4994 struct net_device *dev,
4995 struct cfg80211_ibss_params *params
4996 )
4997{
4998 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4999 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5000 tCsrRoamProfile *pRoamProfile;
5001 int status;
5002 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5003
5004 ENTER();
5005
5006 hddLog(VOS_TRACE_LEVEL_INFO,
5007 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5008
5009 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5010 {
5011 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5012 "%s:LOGP in Progress. Ignore!!!", __func__);
5013 return -EAGAIN;
5014 }
5015
5016 if (NULL == pWextState)
5017 {
5018 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5019 __func__);
5020 return -EIO;
5021 }
5022
5023 pRoamProfile = &pWextState->roamProfile;
5024
5025 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
5026 {
5027 hddLog (VOS_TRACE_LEVEL_ERROR,
5028 "%s Interface type is not set to IBSS \n", __func__);
5029 return -EINVAL;
5030 }
5031
5032 /* Set Channel */
5033 if (NULL != params->channel)
5034 {
5035 u8 channelNum;
5036 if (IEEE80211_BAND_5GHZ == params->channel->band)
5037 {
5038 hddLog(VOS_TRACE_LEVEL_ERROR,
5039 "%s: IBSS join is called with unsupported band %d",
5040 __func__, params->channel->band);
5041 return -EOPNOTSUPP;
5042 }
5043
5044 /* Get channel number */
5045 channelNum =
5046 ieee80211_frequency_to_channel(params->channel->center_freq);
5047
5048 /*TODO: use macro*/
5049 if (14 >= channelNum)
5050 {
5051 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5052 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5053 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5054 int indx;
5055
5056 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5057 validChan, &numChans))
5058 {
5059 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
5060 __func__);
5061 return -EOPNOTSUPP;
5062 }
5063
5064 for (indx = 0; indx < numChans; indx++)
5065 {
5066 if (channelNum == validChan[indx])
5067 {
5068 break;
5069 }
5070 }
5071 if (indx >= numChans)
5072 {
5073 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
5074 __func__, channelNum);
5075 return -EINVAL;
5076 }
5077 /* Set the Operational Channel */
5078 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
5079 channelNum);
5080 pRoamProfile->ChannelInfo.numOfChannels = 1;
5081 pHddStaCtx->conn_info.operationChannel = channelNum;
5082 pRoamProfile->ChannelInfo.ChannelList =
5083 &pHddStaCtx->conn_info.operationChannel;
5084 }
5085 else
5086 {
5087 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5088 __func__, channelNum);
5089 return -EINVAL;
5090 }
5091 }
5092
5093 /* Initialize security parameters */
5094 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5095 if (status < 0)
5096 {
5097 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5098 __func__);
5099 return status;
5100 }
5101
5102 /* Issue connect start */
5103 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005104 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005105
5106 if (0 > status)
5107 {
5108 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5109 return status;
5110 }
5111
5112 return 0;
5113}
5114
5115/*
5116 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5117 * This function is used to leave an IBSS
5118 */
5119static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5120 struct net_device *dev
5121 )
5122{
5123 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5124 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5125 tCsrRoamProfile *pRoamProfile;
5126
5127 ENTER();
5128
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005129 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5130 {
5131 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5132 "%s:LOGP in Progress. Ignore!!!", __func__);
5133 return -EAGAIN;
5134 }
5135
Jeff Johnson295189b2012-06-20 16:38:30 -07005136 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5137 if (NULL == pWextState)
5138 {
5139 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5140 __func__);
5141 return -EIO;
5142 }
5143
5144 pRoamProfile = &pWextState->roamProfile;
5145
5146 /* Issue disconnect only if interface type is set to IBSS */
5147 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5148 {
5149 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5150 __func__);
5151 return -EINVAL;
5152 }
5153
5154 /* Issue Disconnect request */
5155 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5156 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5157 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5158
5159 return 0;
5160}
5161
5162/*
5163 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5164 * This function is used to set the phy parameters
5165 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5166 */
5167static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5168 u32 changed)
5169{
5170 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5171 tHalHandle hHal = pHddCtx->hHal;
5172
5173 ENTER();
5174
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005175 if ( pHddCtx->isLogpInProgress )
5176 {
5177 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5178 "%s:LOGP in Progress. Ignore!!!", __func__);
5179 return -EAGAIN;
5180 }
5181
Jeff Johnson295189b2012-06-20 16:38:30 -07005182 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
5183 {
5184 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
5185 WNI_CFG_RTS_THRESHOLD_STAMAX :
5186 wiphy->rts_threshold;
5187
5188 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
5189 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
5190 {
5191 hddLog(VOS_TRACE_LEVEL_ERROR,
5192 "%s: Invalid RTS Threshold value %hu",
5193 __func__, rts_threshold);
5194 return -EINVAL;
5195 }
5196
5197 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
5198 rts_threshold, ccmCfgSetCallback,
5199 eANI_BOOLEAN_TRUE))
5200 {
5201 hddLog(VOS_TRACE_LEVEL_ERROR,
5202 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
5203 __func__, rts_threshold);
5204 return -EIO;
5205 }
5206
5207 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
5208 rts_threshold);
5209 }
5210
5211 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
5212 {
5213 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
5214 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
5215 wiphy->frag_threshold;
5216
5217 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
5218 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
5219 {
5220 hddLog(VOS_TRACE_LEVEL_ERROR,
5221 "%s: Invalid frag_threshold value %hu", __func__,
5222 frag_threshold);
5223 return -EINVAL;
5224 }
5225
5226 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
5227 frag_threshold, ccmCfgSetCallback,
5228 eANI_BOOLEAN_TRUE))
5229 {
5230 hddLog(VOS_TRACE_LEVEL_ERROR,
5231 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
5232 __func__, frag_threshold);
5233 return -EIO;
5234 }
5235
5236 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
5237 frag_threshold);
5238 }
5239
5240 if ((changed & WIPHY_PARAM_RETRY_SHORT)
5241 || (changed & WIPHY_PARAM_RETRY_LONG))
5242 {
5243 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
5244 wiphy->retry_short :
5245 wiphy->retry_long;
5246
5247 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
5248 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
5249 {
5250 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
5251 __func__, retry_value);
5252 return -EINVAL;
5253 }
5254
5255 if (changed & WIPHY_PARAM_RETRY_SHORT)
5256 {
5257 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
5258 retry_value, ccmCfgSetCallback,
5259 eANI_BOOLEAN_TRUE))
5260 {
5261 hddLog(VOS_TRACE_LEVEL_ERROR,
5262 "%s: ccmCfgSetInt failed for long retry count %hu",
5263 __func__, retry_value);
5264 return -EIO;
5265 }
5266 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
5267 __func__, retry_value);
5268 }
5269 else if (changed & WIPHY_PARAM_RETRY_SHORT)
5270 {
5271 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
5272 retry_value, ccmCfgSetCallback,
5273 eANI_BOOLEAN_TRUE))
5274 {
5275 hddLog(VOS_TRACE_LEVEL_ERROR,
5276 "%s: ccmCfgSetInt failed for short retry count %hu",
5277 __func__, retry_value);
5278 return -EIO;
5279 }
5280 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
5281 __func__, retry_value);
5282 }
5283 }
5284
5285 return 0;
5286}
5287
5288/*
5289 * FUNCTION: wlan_hdd_cfg80211_set_txpower
5290 * This function is used to set the txpower
5291 */
5292static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
5293#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
5294 enum tx_power_setting type,
5295#else
5296 enum nl80211_tx_power_setting type,
5297#endif
5298 int dbm)
5299{
5300 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5301 tHalHandle hHal = pHddCtx->hHal;
5302 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5303 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5304
5305 ENTER();
5306
5307 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
5308 dbm, ccmCfgSetCallback,
5309 eANI_BOOLEAN_TRUE))
5310 {
5311 hddLog(VOS_TRACE_LEVEL_ERROR,
5312 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
5313 return -EIO;
5314 }
5315
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005316 if ( pHddCtx->isLogpInProgress )
5317 {
5318 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5319 "%s:LOGP in Progress. Ignore!!!", __func__);
5320 return -EAGAIN;
5321 }
5322
Jeff Johnson295189b2012-06-20 16:38:30 -07005323 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
5324 dbm);
5325
5326 switch(type)
5327 {
5328 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
5329 /* Fall through */
5330 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
5331 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
5332 {
5333 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
5334 __func__);
5335 return -EIO;
5336 }
5337 break;
5338 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
5339 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
5340 __func__);
5341 return -EOPNOTSUPP;
5342 break;
5343 default:
5344 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
5345 __func__, type);
5346 return -EIO;
5347 }
5348
5349 return 0;
5350}
5351
5352/*
5353 * FUNCTION: wlan_hdd_cfg80211_get_txpower
5354 * This function is used to read the txpower
5355 */
5356static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
5357{
5358
5359 hdd_adapter_t *pAdapter;
5360 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5361
Jeff Johnsone7245742012-09-05 17:12:55 -07005362 ENTER();
5363
Jeff Johnson295189b2012-06-20 16:38:30 -07005364 if (NULL == pHddCtx)
5365 {
5366 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
5367 *dbm = 0;
5368 return -ENOENT;
5369 }
5370
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005371 if ( pHddCtx->isLogpInProgress )
5372 {
5373 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5374 "%s:LOGP in Progress. Ignore!!!", __func__);
5375 return -EAGAIN;
5376 }
5377
Jeff Johnson295189b2012-06-20 16:38:30 -07005378 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5379 if (NULL == pAdapter)
5380 {
5381 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
5382 return -ENOENT;
5383 }
5384
5385 wlan_hdd_get_classAstats(pAdapter);
5386 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
5387
Jeff Johnsone7245742012-09-05 17:12:55 -07005388 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005389 return 0;
5390}
5391
5392static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
5393 u8* mac, struct station_info *sinfo)
5394{
5395 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5396 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5397 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
5398 tANI_U8 rate_flags;
5399
5400 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5401 hdd_config_t *pCfg = pHddCtx->cfg_ini;
5402 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5403
5404 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
5405 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
5406 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
5407 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
5408 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
5409 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
5410 tANI_U16 maxRate = 0;
5411 tANI_U16 myRate;
5412 tANI_U16 currentRate = 0;
5413 tANI_U8 maxSpeedMCS = 0;
5414 tANI_U8 maxMCSIdx = 0;
5415 tANI_U8 rateFlag = 1;
5416 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005417 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07005418
Jeff Johnsone7245742012-09-05 17:12:55 -07005419 ENTER();
5420
Jeff Johnson295189b2012-06-20 16:38:30 -07005421 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
5422 (0 == ssidlen))
5423 {
5424 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
5425 " Invalid ssidlen, %d", __func__, ssidlen);
5426 /*To keep GUI happy*/
5427 return 0;
5428 }
5429
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005430 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5431 {
5432 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5433 "%s:LOGP in Progress. Ignore!!!", __func__);
5434 return -EAGAIN;
5435 }
5436
Jeff Johnson295189b2012-06-20 16:38:30 -07005437 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
5438 sinfo->filled |= STATION_INFO_SIGNAL;
5439
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005440 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005441 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
5442
5443 //convert to the UI units of 100kbps
5444 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
5445
5446#ifdef LINKSPEED_DEBUG_ENABLED
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005447 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 -07005448 sinfo->signal,
5449 pCfg->reportMaxLinkSpeed,
5450 myRate,
5451 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005452 (int) pCfg->linkSpeedRssiMid,
5453 (int) pCfg->linkSpeedRssiLow,
5454 (int) rate_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005455#endif //LINKSPEED_DEBUG_ENABLED
5456
5457 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
5458 {
5459 // we do not want to necessarily report the current speed
5460 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
5461 {
5462 // report the max possible speed
5463 rssidx = 0;
5464 }
5465 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
5466 {
5467 // report the max possible speed with RSSI scaling
5468 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
5469 {
5470 // report the max possible speed
5471 rssidx = 0;
5472 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005473 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07005474 {
5475 // report middle speed
5476 rssidx = 1;
5477 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005478 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
5479 {
5480 // report middle speed
5481 rssidx = 2;
5482 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005483 else
5484 {
5485 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005486 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07005487 }
5488 }
5489 else
5490 {
5491 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
5492 hddLog(VOS_TRACE_LEVEL_ERROR,
5493 "%s: Invalid value for reportMaxLinkSpeed: %u",
5494 __func__, pCfg->reportMaxLinkSpeed);
5495 rssidx = 0;
5496 }
5497
5498 maxRate = 0;
5499
5500 /* Get Basic Rate Set */
5501 ccmCfgGetStr(hHal, WNI_CFG_OPERATIONAL_RATE_SET, OperationalRates, &ORLeng);
5502 for (i = 0; i < ORLeng; i++)
5503 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005504 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005505 {
5506 /* Validate Rate Set */
5507 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
5508 {
5509 currentRate = supported_data_rate[j].supported_rate[rssidx];
5510 break;
5511 }
5512 }
5513 /* Update MAX rate */
5514 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5515 }
5516
5517 /* Get Extended Rate Set */
5518 ccmCfgGetStr(hHal, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, ExtendedRates, &ERLeng);
5519 for (i = 0; i < ERLeng; i++)
5520 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005521 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005522 {
5523 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
5524 {
5525 currentRate = supported_data_rate[j].supported_rate[rssidx];
5526 break;
5527 }
5528 }
5529 /* Update MAX rate */
5530 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5531 }
5532
5533 /* Get MCS Rate Set -- but only if we are connected at MCS
5534 rates or if we are always reporting max speed or if we have
5535 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005536 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07005537 {
5538 ccmCfgGetStr(hHal, WNI_CFG_CURRENT_MCS_SET, MCSRates, &MCSLeng);
5539 rateFlag = 0;
5540 if (rate_flags & eHAL_TX_RATE_HT40)
5541 {
5542 rateFlag |= 1;
5543 }
5544 if (rate_flags & eHAL_TX_RATE_SGI)
5545 {
5546 rateFlag |= 2;
5547 }
5548
5549 for (i = 0; i < MCSLeng; i++)
5550 {
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005551 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
5552 for (j = 0; j < temp; j++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005553 {
5554 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
5555 {
5556 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
5557 break;
5558 }
5559 }
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005560 if ((j < temp) && (currentRate > maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07005561 {
5562 maxRate = currentRate;
5563 maxSpeedMCS = 1;
5564 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
5565 }
5566 }
5567 }
5568
5569 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005570 if (((maxRate < myRate) && (0 == rssidx)) ||
5571 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07005572 {
5573 maxRate = myRate;
5574 if (rate_flags & eHAL_TX_RATE_LEGACY)
5575 {
5576 maxSpeedMCS = 0;
5577 }
5578 else
5579 {
5580 maxSpeedMCS = 1;
5581 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
5582 }
5583 }
5584
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005585 if ((!maxSpeedMCS) || (0 != rssidx))
Jeff Johnson295189b2012-06-20 16:38:30 -07005586 {
5587 sinfo->txrate.legacy = maxRate;
5588#ifdef LINKSPEED_DEBUG_ENABLED
5589 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
5590#endif //LINKSPEED_DEBUG_ENABLED
5591 }
5592 else
5593 {
5594 sinfo->txrate.mcs = maxMCSIdx;
5595 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
5596 if (rate_flags & eHAL_TX_RATE_SGI)
5597 {
5598 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
5599 }
5600 if (rate_flags & eHAL_TX_RATE_HT40)
5601 {
5602 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
5603 }
5604#ifdef LINKSPEED_DEBUG_ENABLED
5605 pr_info("Reporting MCS rate %d flags %x\n",
5606 sinfo->txrate.mcs,
5607 sinfo->txrate.flags );
5608#endif //LINKSPEED_DEBUG_ENABLED
5609 }
5610 }
5611 else
5612 {
5613 // report current rate instead of max rate
5614
5615 if (rate_flags & eHAL_TX_RATE_LEGACY)
5616 {
5617 //provide to the UI in units of 100kbps
5618 sinfo->txrate.legacy = myRate;
5619#ifdef LINKSPEED_DEBUG_ENABLED
5620 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
5621#endif //LINKSPEED_DEBUG_ENABLED
5622 }
5623 else
5624 {
5625 //must be MCS
5626 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
5627 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
5628 if (rate_flags & eHAL_TX_RATE_SGI)
5629 {
5630 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
5631 }
5632 if (rate_flags & eHAL_TX_RATE_HT40)
5633 {
5634 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
5635 }
5636#ifdef LINKSPEED_DEBUG_ENABLED
5637 pr_info("Reporting actual MCS rate %d flags %x\n",
5638 sinfo->txrate.mcs,
5639 sinfo->txrate.flags );
5640#endif //LINKSPEED_DEBUG_ENABLED
5641 }
5642 }
5643 sinfo->filled |= STATION_INFO_TX_BITRATE;
5644
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005645 sinfo->tx_packets =
5646 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
5647 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
5648 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
5649 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
5650
5651 sinfo->tx_retries =
5652 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
5653 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
5654 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
5655 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
5656
5657 sinfo->tx_failed =
5658 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
5659 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
5660 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
5661 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
5662
5663 sinfo->filled |=
5664 STATION_INFO_TX_PACKETS |
5665 STATION_INFO_TX_RETRIES |
5666 STATION_INFO_TX_FAILED;
5667
5668 EXIT();
5669 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005670}
5671
5672static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
5673 struct net_device *dev, bool mode, v_SINT_t timeout)
5674{
5675 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5676 VOS_STATUS vos_status;
5677
Jeff Johnsone7245742012-09-05 17:12:55 -07005678 ENTER();
5679
Jeff Johnson295189b2012-06-20 16:38:30 -07005680 if (NULL == pAdapter)
5681 {
5682 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
5683 return -ENODEV;
5684 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005685 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5686 {
5687 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5688 "%s:LOGP in Progress. Ignore!!!", __func__);
5689 return -EAGAIN;
5690 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005691
5692 /**The get power cmd from the supplicant gets updated by the nl only
5693 *on successful execution of the function call
5694 *we are oppositely mapped w.r.t mode in the driver
5695 **/
5696 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
5697
Jeff Johnsone7245742012-09-05 17:12:55 -07005698 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005699 if (VOS_STATUS_E_FAILURE == vos_status)
5700 {
5701 return -EINVAL;
5702 }
5703 return 0;
5704}
5705
5706
5707#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5708static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
5709 struct net_device *netdev,
5710 u8 key_index)
5711{
Jeff Johnsone7245742012-09-05 17:12:55 -07005712 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005713 return 0;
5714}
5715#endif //LINUX_VERSION_CODE
5716
5717#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
5718static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
5719 struct net_device *dev,
5720 struct ieee80211_txq_params *params)
5721{
Jeff Johnsone7245742012-09-05 17:12:55 -07005722 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005723 return 0;
5724}
5725#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5726static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
5727 struct ieee80211_txq_params *params)
5728{
Jeff Johnsone7245742012-09-05 17:12:55 -07005729 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005730 return 0;
5731}
5732#endif //LINUX_VERSION_CODE
5733
5734static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
5735 struct net_device *dev, u8 *mac)
5736{
5737 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5738
Jeff Johnsone7245742012-09-05 17:12:55 -07005739 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005740 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
5741 {
5742 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
5743 return -EINVAL;
5744 }
5745
5746 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
5747 {
5748 hddLog( LOGE,
5749 "%s: Wlan Load/Unload is in progress", __func__);
5750 return -EBUSY;
5751 }
5752
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005753 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5754 {
5755 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5756 "%s:LOGP in Progress. Ignore!!!", __func__);
5757 return -EAGAIN;
5758 }
5759
Jeff Johnson295189b2012-06-20 16:38:30 -07005760 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
5761#ifdef WLAN_FEATURE_P2P
5762 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
5763#endif
5764 )
5765 {
5766 if( NULL == mac )
5767 {
5768 v_U16_t i;
5769 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
5770 {
5771 if(pAdapter->aStaInfo[i].isUsed)
5772 {
5773 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
5774 hddLog(VOS_TRACE_LEVEL_INFO,
5775 "%s: Delete STA with MAC::"
5776 "%02x:%02x:%02x:%02x:%02x:%02x",
5777 __func__,
5778 macAddr[0], macAddr[1], macAddr[2],
5779 macAddr[3], macAddr[4], macAddr[5]);
5780 hdd_softap_sta_deauth(pAdapter, macAddr);
5781 }
5782 }
5783 }
5784 else
5785 {
5786 hddLog(VOS_TRACE_LEVEL_INFO,
5787 "%s: Delete STA with MAC::"
5788 "%02x:%02x:%02x:%02x:%02x:%02x",
5789 __func__,
5790 mac[0], mac[1], mac[2],
5791 mac[3], mac[4], mac[5]);
5792 hdd_softap_sta_deauth(pAdapter, mac);
5793 }
5794 }
5795
5796 EXIT();
5797
5798 return 0;
5799}
5800
5801static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
5802 struct net_device *dev, u8 *mac, struct station_parameters *params)
5803{
5804 // TODO: Implement this later.
Jeff Johnsone7245742012-09-05 17:12:55 -07005805 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005806 return 0;
5807}
5808
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005809
5810#ifdef FEATURE_WLAN_LFR
5811static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07005812 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005813{
5814#define MAX_PMKSAIDS_IN_CACHE 8
5815 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -07005816 static tANI_U32 i; // HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005817 tANI_U32 j=0;
5818 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5819 tHalHandle halHandle;
5820 eHalStatus result;
5821 tANI_U8 BSSIDMatched = 0;
5822
Jeff Johnsone7245742012-09-05 17:12:55 -07005823 ENTER();
5824
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005825 // Validate pAdapter
5826 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
5827 {
5828 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
5829 return -EINVAL;
5830 }
5831
5832 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
5833 {
5834 hddLog( LOGE,
5835 "%s: Wlan Load/Unload is in progress", __func__);
5836 return -EBUSY;
5837 }
5838
5839 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5840 {
5841 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5842 "%s:LOGP in Progress. Ignore!!!", __func__);
5843 return -EAGAIN;
5844 }
5845
5846 // Retrieve halHandle
5847 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
5848
5849 for (j = 0; j < i; j++)
5850 {
5851 if(vos_mem_compare(PMKIDCache[j].BSSID,
5852 pmksa->bssid, WNI_CFG_BSSID_LEN))
5853 {
5854 /* BSSID matched previous entry. Overwrite it. */
5855 BSSIDMatched = 1;
5856 vos_mem_copy(PMKIDCache[j].BSSID,
5857 pmksa->bssid, WNI_CFG_BSSID_LEN);
5858 vos_mem_copy(PMKIDCache[j].PMKID,
5859 pmksa->pmkid,
5860 CSR_RSN_PMKID_SIZE);
5861 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005862 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005863 dump_bssid(pmksa->bssid);
5864 dump_pmkid(halHandle, pmksa->pmkid);
5865 break;
5866 }
5867 }
5868
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07005869 /* Check we compared all entries,if then take the first slot now */
5870 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
5871
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005872 if (!BSSIDMatched)
5873 {
5874 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
5875 vos_mem_copy(PMKIDCache[i].BSSID,
5876 pmksa->bssid, ETHER_ADDR_LEN);
5877 vos_mem_copy(PMKIDCache[i].PMKID,
5878 pmksa->pmkid,
5879 CSR_RSN_PMKID_SIZE);
5880 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005881 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005882 dump_bssid(pmksa->bssid);
5883 dump_pmkid(halHandle, pmksa->pmkid);
5884 // Increment the HDD Local Cache index
5885 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
5886 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
5887 }
5888
5889
5890 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
5891 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005892 // __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005893 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005894 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005895 // Finally set the PMKSA ID Cache in CSR
5896 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
5897 PMKIDCache,
5898 i );
5899 return 0;
5900}
5901
5902
5903static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07005904 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005905{
Jeff Johnsone7245742012-09-05 17:12:55 -07005906 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005907 // TODO: Implement this later.
5908 return 0;
5909}
5910
5911static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
5912{
Jeff Johnsone7245742012-09-05 17:12:55 -07005913 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005914 // TODO: Implement this later.
5915 return 0;
5916}
5917#endif
5918
5919
Jeff Johnson295189b2012-06-20 16:38:30 -07005920/* cfg80211_ops */
5921static struct cfg80211_ops wlan_hdd_cfg80211_ops =
5922{
5923 .add_virtual_intf = wlan_hdd_add_virtual_intf,
5924 .del_virtual_intf = wlan_hdd_del_virtual_intf,
5925 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
5926 .change_station = wlan_hdd_change_station,
5927#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
5928 .add_beacon = wlan_hdd_cfg80211_add_beacon,
5929 .del_beacon = wlan_hdd_cfg80211_del_beacon,
5930 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005931#else
5932 .start_ap = wlan_hdd_cfg80211_start_ap,
5933 .change_beacon = wlan_hdd_cfg80211_change_beacon,
5934 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07005935#endif
5936 .change_bss = wlan_hdd_cfg80211_change_bss,
5937 .add_key = wlan_hdd_cfg80211_add_key,
5938 .get_key = wlan_hdd_cfg80211_get_key,
5939 .del_key = wlan_hdd_cfg80211_del_key,
5940 .set_default_key = wlan_hdd_cfg80211_set_default_key,
5941 .set_channel = wlan_hdd_cfg80211_set_channel,
5942 .scan = wlan_hdd_cfg80211_scan,
5943 .connect = wlan_hdd_cfg80211_connect,
5944 .disconnect = wlan_hdd_cfg80211_disconnect,
5945 .join_ibss = wlan_hdd_cfg80211_join_ibss,
5946 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
5947 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
5948 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
5949 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
5950#ifdef WLAN_FEATURE_P2P
5951 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
5952 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
5953 .mgmt_tx = wlan_hdd_action,
5954#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5955 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
5956 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
5957 .set_txq_params = wlan_hdd_set_txq_params,
5958#endif
5959#endif
5960 .get_station = wlan_hdd_cfg80211_get_station,
5961 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
5962 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005963 .add_station = wlan_hdd_cfg80211_add_station,
5964#ifdef FEATURE_WLAN_LFR
5965 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
5966 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
5967 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
5968#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005969};
5970
5971#endif // CONFIG_CFG80211