blob: 0e13df212c8721f45a87befa9cb991ad1968f758 [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;
351 v_U16_t supported_rate[3];
352} supported_data_rate[] =
353{
354/* IDX HI MID LO (RSSI-based index */
355 {2, { 10, 10, 0}},
356 {4, { 20, 20, 0}},
357 {11, { 55, 55, 0}},
358 {12, { 60, 60, 0}},
359 {18, { 90, 90, 0}},
360 {22, {110, 55, 0}},
361 {24, {120, 120, 0}},
362 {36, {180, 180, 0}},
363 {44, {220, 220, 0}},
364 {48, {240, 240, 0}},
365 {66, {330, 240, 0}},
366 {72, {360, 240, 0}},
367 {96, {480, 240, 0}},
368 {108, {540, 240, 0}}
369};
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
460 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
461 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
462 | WIPHY_FLAG_CUSTOM_REGULATORY;
463
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700464#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnsone7245742012-09-05 17:12:55 -0700465 wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
466 | 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 }
1305 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001306 else
1307 {
1308 pConfig->ieee80211d = 0;
1309 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001310 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001311 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001312 {
1313 pConfig->ieee80211d = 0;
1314 }
1315 pConfig->authType = eSAP_AUTO_SWITCH;
1316
1317 capab_info = pMgmt_frame->u.beacon.capab_info;
1318
1319 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
1320 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1321
1322 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1323
1324 /*Set wps station to configured*/
1325 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1326
1327 if(pIe)
1328 {
1329 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1330 {
1331 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1332 return -EINVAL;
1333 }
1334 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1335 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001336 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001337 /* Check 15 bit of WPS IE as it contain information for wps state
1338 * WPS state
1339 */
1340 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1341 {
1342 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1343 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1344 {
1345 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1346 }
1347 }
1348 }
1349 else
1350 {
1351 pConfig->wps_state = SAP_WPS_DISABLED;
1352 }
1353 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
1354
1355 pConfig->RSNWPAReqIELength = 0;
1356 pConfig->pRSNWPAReqIE = NULL;
1357 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1358 WLAN_EID_RSN);
1359 if(pIe && pIe[1])
1360 {
1361 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1362 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1363 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1364 /* The actual processing may eventually be more extensive than
1365 * this. Right now, just consume any PMKIDs that are sent in
1366 * by the app.
1367 * */
1368 status = hdd_softap_unpackIE(
1369 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1370 &RSNEncryptType,
1371 &mcRSNEncryptType,
1372 &RSNAuthType,
1373 pConfig->pRSNWPAReqIE[1]+2,
1374 pConfig->pRSNWPAReqIE );
1375
1376 if( VOS_STATUS_SUCCESS == status )
1377 {
1378 /* Now copy over all the security attributes you have
1379 * parsed out
1380 * */
1381 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1382 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1383 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1384 = RSNEncryptType;
1385 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1386 "EncryptionType = %d mcEncryptionType = %d\n"),
1387 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1388 }
1389 }
1390
1391 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1392 pBeacon->tail, pBeacon->tail_len);
1393
1394 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1395 {
1396 if (pConfig->pRSNWPAReqIE)
1397 {
1398 /*Mixed mode WPA/WPA2*/
1399 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1400 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1401 }
1402 else
1403 {
1404 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1405 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1406 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1407 status = hdd_softap_unpackIE(
1408 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1409 &RSNEncryptType,
1410 &mcRSNEncryptType,
1411 &RSNAuthType,
1412 pConfig->pRSNWPAReqIE[1]+2,
1413 pConfig->pRSNWPAReqIE );
1414
1415 if( VOS_STATUS_SUCCESS == status )
1416 {
1417 /* Now copy over all the security attributes you have
1418 * parsed out
1419 * */
1420 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1421 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1422 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1423 = RSNEncryptType;
1424 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1425 "EncryptionType = %d mcEncryptionType = %d\n"),
1426 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1427 }
1428 }
1429 }
1430
1431 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1432
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001433#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001434 if (params->ssid != NULL)
1435 {
1436 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1437 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1438 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1439 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1440 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001441#else
1442 if (ssid != NULL)
1443 {
1444 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1445 pConfig->SSIDinfo.ssid.length = ssid_len;
1446 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1447 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1448 }
1449#endif
1450
Jeff Johnson295189b2012-06-20 16:38:30 -07001451 vos_mem_copy(pConfig->self_macaddr.bytes,
1452 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1453
1454 /* default value */
1455 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1456 pConfig->num_accept_mac = 0;
1457 pConfig->num_deny_mac = 0;
1458
1459 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1460 pBeacon->tail, pBeacon->tail_len);
1461
1462 /* pIe for black list is following form:
1463 type : 1 byte
1464 length : 1 byte
1465 OUI : 4 bytes
1466 acl type : 1 byte
1467 no of mac addr in black list: 1 byte
1468 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1469 */
1470 if ((pIe != NULL) && (pIe[1] != 0))
1471 {
1472 pConfig->SapMacaddr_acl = pIe[6];
1473 pConfig->num_deny_mac = pIe[7];
1474 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1475 pIe[6], pIe[7]);
1476 if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
1477 pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
1478 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1479 for (i = 0; i < pConfig->num_deny_mac; i++)
1480 {
1481 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1482 acl_entry++;
1483 }
1484 }
1485 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1486 pBeacon->tail, pBeacon->tail_len);
1487
1488 /* pIe for white list is following form:
1489 type : 1 byte
1490 length : 1 byte
1491 OUI : 4 bytes
1492 acl type : 1 byte
1493 no of mac addr in white list: 1 byte
1494 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1495 */
1496 if ((pIe != NULL) && (pIe[1] != 0))
1497 {
1498 pConfig->SapMacaddr_acl = pIe[6];
1499 pConfig->num_accept_mac = pIe[7];
1500 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
1501 pIe[6], pIe[7]);
1502 if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
1503 pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
1504 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1505 for (i = 0; i < pConfig->num_accept_mac; i++)
1506 {
1507 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1508 acl_entry++;
1509 }
1510 }
1511 wlan_hdd_set_sapHwmode(pHostapdAdapter);
1512
Jeff Johnsone7245742012-09-05 17:12:55 -07001513#ifdef WLAN_FEATURE_11AC
1514 if(((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
1515 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1516 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) )
1517 {
1518 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
1519 }
1520#endif
1521
Jeff Johnson295189b2012-06-20 16:38:30 -07001522 // ht_capab is not what the name conveys,this is used for protection bitmap
1523 pConfig->ht_capab =
1524 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
1525
1526 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
1527 {
1528 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
1529 return -EINVAL;
1530 }
1531
1532 //Uapsd Enabled Bit
1533 pConfig->UapsdEnable =
1534 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
1535 //Enable OBSS protection
1536 pConfig->obssProtEnabled =
1537 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
1538
1539 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
1540 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
1541 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
1542 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
1543 (int)pConfig->channel);
1544 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
1545 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
1546 pConfig->authType);
1547 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
1548 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
1549 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
1550 pConfig->protEnabled, pConfig->obssProtEnabled);
1551
1552 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
1553 {
1554 //Bss already started. just return.
1555 //TODO Probably it should update some beacon params.
1556 hddLog( LOGE, "Bss Already started...Ignore the request");
1557 EXIT();
1558 return 0;
1559 }
1560
1561 pConfig->persona = pHostapdAdapter->device_mode;
1562
1563 pSapEventCallback = hdd_hostapd_SAPEventCB;
1564 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
1565 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
1566 {
1567 hddLog(LOGE,FL("SAP Start Bss fail\n"));
1568 return -EINVAL;
1569 }
1570
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001571 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07001572 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
1573
1574 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1575
1576 if (!VOS_IS_STATUS_SUCCESS(status))
1577 {
1578 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1579 ("ERROR: HDD vos wait for single_event failed!!\n"));
1580 VOS_ASSERT(0);
1581 }
1582
1583 //Succesfully started Bss update the state bit.
1584 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
1585
1586 pHostapdState->bCommit = TRUE;
1587 EXIT();
1588
1589 return 0;
1590}
1591
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001592#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001593static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
1594 struct net_device *dev,
1595 struct beacon_parameters *params)
1596{
1597 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1598 int status=VOS_STATUS_SUCCESS;
1599
1600 ENTER();
1601
1602 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
1603
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001604 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1605 {
1606 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1607 "%s:LOGP in Progress. Ignore!!!", __func__);
1608 return -EAGAIN;
1609 }
1610
Jeff Johnson295189b2012-06-20 16:38:30 -07001611 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
1612#ifdef WLAN_FEATURE_P2P
1613 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1614#endif
1615 )
1616 {
1617 beacon_data_t *old,*new;
1618
1619 old = pAdapter->sessionCtx.ap.beacon;
1620
1621 if (old)
1622 return -EALREADY;
1623
1624 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
1625
1626 if(status != VOS_STATUS_SUCCESS)
1627 {
1628 hddLog(VOS_TRACE_LEVEL_FATAL,
1629 "%s:Error!!! Allocating the new beacon\n",__func__);
1630 return -EINVAL;
1631 }
1632
1633 pAdapter->sessionCtx.ap.beacon = new;
1634
1635 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
1636 }
1637
1638 EXIT();
1639 return status;
1640}
1641
1642static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
1643 struct net_device *dev,
1644 struct beacon_parameters *params)
1645{
1646 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1647 int status=VOS_STATUS_SUCCESS;
1648
1649 ENTER();
1650
1651 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1652 __func__,pAdapter->device_mode);
1653
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001654 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1655 {
1656 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1657 "%s:LOGP in Progress. Ignore!!!", __func__);
1658 return -EAGAIN;
1659 }
1660
Jeff Johnson295189b2012-06-20 16:38:30 -07001661 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1662#ifdef WLAN_FEATURE_P2P
1663 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1664#endif
1665 )
1666 {
1667 beacon_data_t *old,*new;
1668
1669 old = pAdapter->sessionCtx.ap.beacon;
1670
1671 if (!old)
1672 return -ENOENT;
1673
1674 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
1675
1676 if(status != VOS_STATUS_SUCCESS) {
1677 hddLog(VOS_TRACE_LEVEL_FATAL,
1678 "%s: Error!!! Allocating the new beacon\n",__func__);
1679 return -EINVAL;
1680 }
1681
1682 pAdapter->sessionCtx.ap.beacon = new;
1683
1684 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
1685 }
1686
1687 EXIT();
1688 return status;
1689}
1690
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001691#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1692
1693#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001694static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
1695 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001696#else
1697static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
1698 struct net_device *dev)
1699#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001700{
1701 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07001702 hdd_context_t *pHddCtx = NULL;
1703 hdd_scaninfo_t *pScanInfo = NULL;
1704 hdd_adapter_t *staAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001705 VOS_STATUS status = 0;
1706
1707 ENTER();
1708
1709 if (NULL == pAdapter)
1710 {
1711 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1712 "%s: HDD adapter context is Null", __FUNCTION__);
1713 return -ENODEV;
1714 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001715
1716 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1717 if (NULL == pHddCtx)
1718 {
1719 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1720 "%s: HDD context is Null", __FUNCTION__);
1721 return -ENODEV;
1722 }
1723
1724 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
1725 if (NULL == staAdapter)
1726 {
1727 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
1728 if (NULL == staAdapter)
1729 {
1730 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1731 "%s: HDD adapter context is Null", __FUNCTION__);
1732 return -ENODEV;
1733 }
1734 }
1735
1736 pScanInfo = &pHddCtx->scan_info;
1737
Jeff Johnson295189b2012-06-20 16:38:30 -07001738 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1739 {
1740 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1741 return -EAGAIN;
1742 }
1743
1744 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1745
1746 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1747 __func__,pAdapter->device_mode);
1748
Jeff Johnsone7245742012-09-05 17:12:55 -07001749 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
1750 {
1751 INIT_COMPLETION(staAdapter->abortscan_event_var);
1752 hdd_abort_mac_scan(staAdapter->pHddCtx);
1753 status = wait_for_completion_interruptible_timeout(
1754 &staAdapter->abortscan_event_var,
1755 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
1756 if (!status)
1757 {
1758 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1759 "%s: Timeout occured while waiting for abortscan" ,
1760 __FUNCTION__);
1761 VOS_ASSERT(pScanInfo->mScanPending);
1762 return 0;
1763 }
1764 }
1765
Jeff Johnson295189b2012-06-20 16:38:30 -07001766 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1767#ifdef WLAN_FEATURE_P2P
1768 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1769#endif
1770 )
1771 {
1772 beacon_data_t *old;
1773
1774 old = pAdapter->sessionCtx.ap.beacon;
1775
1776 if (!old)
1777 return -ENOENT;
1778
1779#ifdef CONFIG_CFG80211
1780 hdd_cleanup_actionframe(pHddCtx, pAdapter);
1781#endif
1782
1783 mutex_lock(&pHddCtx->sap_lock);
1784 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
1785 {
1786 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss((WLAN_HDD_GET_CTX(pAdapter))->pvosContext) ) )
1787 {
1788 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
1789
1790 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1791
1792 if (!VOS_IS_STATUS_SUCCESS(status))
1793 {
1794 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1795 ("ERROR: HDD vos wait for single_event failed!!\n"));
1796 VOS_ASSERT(0);
1797 }
1798 }
1799 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
1800 }
1801 mutex_unlock(&pHddCtx->sap_lock);
1802
1803 if(status != VOS_STATUS_SUCCESS)
1804 {
1805 hddLog(VOS_TRACE_LEVEL_FATAL,
1806 "%s:Error!!! Stopping the BSS\n",__func__);
1807 return -EINVAL;
1808 }
1809
1810 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
1811 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
1812 ==eHAL_STATUS_FAILURE)
1813 {
1814 hddLog(LOGE,
1815 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
1816 }
1817
1818 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
1819 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1820 eANI_BOOLEAN_FALSE) )
1821 {
1822 hddLog(LOGE,
1823 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1824 }
1825
1826 // Reset WNI_CFG_PROBE_RSP Flags
1827 wlan_hdd_reset_prob_rspies(pAdapter);
1828
1829 pAdapter->sessionCtx.ap.beacon = NULL;
1830 kfree(old);
1831 }
1832 EXIT();
1833 return status;
1834}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001835
1836#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
1837
1838static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
1839 struct net_device *dev,
1840 struct cfg80211_ap_settings *params)
1841{
1842 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1843 int status = VOS_STATUS_SUCCESS;
1844
1845 ENTER();
1846
1847 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n", pAdapter->device_mode);
1848
1849 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1850#ifdef WLAN_FEATURE_P2P
1851 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1852#endif
1853 )
1854 {
1855 beacon_data_t *old,*new;
1856
1857 old = pAdapter->sessionCtx.ap.beacon;
1858
1859 if (old)
1860 return -EALREADY;
1861
1862 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
1863
1864 if(status != VOS_STATUS_SUCCESS)
1865 {
1866 hddLog(VOS_TRACE_LEVEL_FATAL,
1867 "%s:Error!!! Allocating the new beacon\n",__func__);
1868 return -EINVAL;
1869 }
1870 pAdapter->sessionCtx.ap.beacon = new;
1871 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
1872 params->ssid_len, params->hidden_ssid);
1873 }
1874
1875 EXIT();
1876 return status;
1877}
1878
1879
1880static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
1881 struct net_device *dev,
1882 struct cfg80211_beacon_data *params)
1883{
1884 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1885 int status=VOS_STATUS_SUCCESS;
1886
1887 ENTER();
1888
1889 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1890 __func__, pAdapter->device_mode);
1891
1892 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1893#ifdef WLAN_FEATURE_P2P
1894 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1895#endif
1896 )
1897 {
1898 beacon_data_t *old,*new;
1899
1900 old = pAdapter->sessionCtx.ap.beacon;
1901
1902 if (!old)
1903 return -ENOENT;
1904
1905 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
1906
1907 if(status != VOS_STATUS_SUCCESS) {
1908 hddLog(VOS_TRACE_LEVEL_FATAL,
1909 "%s: Error!!! Allocating the new beacon\n",__func__);
1910 return -EINVAL;
1911 }
1912
1913 pAdapter->sessionCtx.ap.beacon = new;
1914
1915 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
1916 }
1917
1918 EXIT();
1919 return status;
1920}
1921
1922#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
1923
Jeff Johnson295189b2012-06-20 16:38:30 -07001924
1925static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
1926 struct net_device *dev,
1927 struct bss_parameters *params)
1928{
1929 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1930
1931 ENTER();
1932
1933 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1934 __func__,pAdapter->device_mode);
1935
1936 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1937#ifdef WLAN_FEATURE_P2P
1938 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1939#endif
1940 )
1941 {
1942 /* ap_isolate == -1 means that in change bss, upper layer doesn't
1943 * want to update this parameter */
1944 if (-1 != params->ap_isolate)
1945 {
1946 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
1947 }
1948 }
1949
1950 EXIT();
1951 return 0;
1952}
1953
1954/*
1955 * FUNCTION: wlan_hdd_cfg80211_change_iface
1956 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
1957 */
1958int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
1959 struct net_device *ndev,
1960 enum nl80211_iftype type,
1961 u32 *flags,
1962 struct vif_params *params
1963 )
1964{
1965 struct wireless_dev *wdev;
1966 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
1967 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07001968 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001969 tCsrRoamProfile *pRoamProfile = NULL;
1970 eCsrRoamBssType LastBSSType;
1971 hdd_config_t *pConfig = pHddCtx->cfg_ini;
1972 eMib_dot11DesiredBssType connectedBssType;
1973 VOS_STATUS status;
1974
1975 ENTER();
1976
1977 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1978 {
1979 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1980 return -EAGAIN;
1981 }
1982
1983 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
1984 __func__, pAdapter->device_mode);
1985
1986 wdev = ndev->ieee80211_ptr;
1987
1988#ifdef WLAN_BTAMP_FEATURE
1989 if((NL80211_IFTYPE_P2P_CLIENT == type)||
1990 (NL80211_IFTYPE_ADHOC == type)||
1991 (NL80211_IFTYPE_AP == type)||
1992 (NL80211_IFTYPE_P2P_GO == type))
1993 {
1994 pHddCtx->isAmpAllowed = VOS_FALSE;
1995 // stop AMP traffic
1996 status = WLANBAP_StopAmp();
1997 if(VOS_STATUS_SUCCESS != status )
1998 {
1999 pHddCtx->isAmpAllowed = VOS_TRUE;
2000 hddLog(VOS_TRACE_LEVEL_FATAL,
2001 "%s: Failed to stop AMP", __func__);
2002 return -EINVAL;
2003 }
2004 }
2005#endif //WLAN_BTAMP_FEATURE
2006 /* Reset the current device mode bit mask*/
2007 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2008
2009 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2010#ifdef WLAN_FEATURE_P2P
2011 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002012 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002013#endif
2014 )
2015 {
2016 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2017 pRoamProfile = &pWextState->roamProfile;
2018 LastBSSType = pRoamProfile->BSSType;
2019
2020 switch (type)
2021 {
2022 case NL80211_IFTYPE_STATION:
2023#ifdef WLAN_FEATURE_P2P
2024 case NL80211_IFTYPE_P2P_CLIENT:
2025#endif
2026 hddLog(VOS_TRACE_LEVEL_INFO,
2027 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2028 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002029#ifdef WLAN_FEATURE_11AC
2030 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2031 {
2032 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2033 }
2034#endif
2035 pRoamProfile->phyMode =
2036 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002037 wdev->iftype = type;
2038#ifdef WLAN_FEATURE_P2P
2039 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2040 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
2041#endif
2042 break;
2043 case NL80211_IFTYPE_ADHOC:
2044 hddLog(VOS_TRACE_LEVEL_INFO,
2045 "%s: setting interface Type to ADHOC", __func__);
2046 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2047 pRoamProfile->phyMode =
2048 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
2049 wdev->iftype = type;
2050 break;
2051
2052 case NL80211_IFTYPE_AP:
2053#ifdef WLAN_FEATURE_P2P
2054 case NL80211_IFTYPE_P2P_GO:
2055#endif
2056 {
2057 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2058 "%s: setting interface Type to %s", __func__,
2059 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2060
Mohit Khanna0f232092012-09-11 14:46:08 -07002061 if (NL80211_IFTYPE_AP == type)
2062 {
2063 /* As Loading WLAN Driver one interface being created for p2p device
2064 * address. This will take one HW STA and the max number of clients
2065 * that can connect to softAP will be reduced by one. so while changing
2066 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2067 * interface as it is not required in SoftAP mode.
2068 */
2069
2070 // Get P2P Adapter
2071 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2072
2073 if (pP2pAdapter)
2074 {
2075 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2076 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2077 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2078 }
2079 }
2080
Jeff Johnson295189b2012-06-20 16:38:30 -07002081 //De-init the adapter.
2082 hdd_stop_adapter( pHddCtx, pAdapter );
2083 hdd_deinit_adapter( pHddCtx, pAdapter );
2084 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2085#ifdef WLAN_SOFTAP_FEATURE
2086#ifdef WLAN_FEATURE_P2P
2087 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2088 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2089#else
2090 pAdapter->device_mode = WLAN_HDD_SOFTAP;
2091#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07002092
2093 //Disable BMPS and IMPS if enabled
2094 //before starting Go
2095 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2096 {
2097 if(VOS_STATUS_E_FAILURE ==
2098 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2099 {
2100 //Fail to Exit BMPS
2101 VOS_ASSERT(0);
2102 }
2103 }
2104
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002105 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2106 (pConfig->apRandomBssidEnabled))
2107 {
2108 /* To meet Android requirements create a randomized
2109 MAC address of the form 02:1A:11:Fx:xx:xx */
2110 get_random_bytes(&ndev->dev_addr[3], 3);
2111 ndev->dev_addr[0] = 0x02;
2112 ndev->dev_addr[1] = 0x1A;
2113 ndev->dev_addr[2] = 0x11;
2114 ndev->dev_addr[3] |= 0xF0;
2115 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2116 VOS_MAC_ADDR_SIZE);
2117 pr_info("wlan: Generated HotSpot BSSID "
2118 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2119 ndev->dev_addr[0],
2120 ndev->dev_addr[1],
2121 ndev->dev_addr[2],
2122 ndev->dev_addr[3],
2123 ndev->dev_addr[4],
2124 ndev->dev_addr[5]);
2125 }
2126
Jeff Johnson295189b2012-06-20 16:38:30 -07002127 hdd_set_ap_ops( pAdapter->dev );
2128
2129 status = hdd_init_ap_mode(pAdapter);
2130 if(status != VOS_STATUS_SUCCESS)
2131 {
2132 hddLog(VOS_TRACE_LEVEL_FATAL,
2133 "%s: Error initializing the ap mode", __func__);
2134 return -EINVAL;
2135 }
2136 hdd_set_conparam(1);
2137
2138#endif
2139 /*interface type changed update in wiphy structure*/
2140 if(wdev)
2141 {
2142 wdev->iftype = type;
2143 pHddCtx->change_iface = type;
2144 }
2145 else
2146 {
2147 hddLog(VOS_TRACE_LEVEL_ERROR,
2148 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2149 return -EINVAL;
2150 }
2151 goto done;
2152 }
2153
2154 default:
2155 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2156 __func__);
2157 return -EOPNOTSUPP;
2158 }
2159 }
2160 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
2161#ifdef WLAN_FEATURE_P2P
2162 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2163#endif
2164 )
2165 {
2166 switch(type)
2167 {
2168 case NL80211_IFTYPE_STATION:
2169#ifdef WLAN_FEATURE_P2P
2170 case NL80211_IFTYPE_P2P_CLIENT:
2171#endif
2172 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002173 hdd_stop_adapter( pHddCtx, pAdapter );
2174 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002175 wdev->iftype = type;
2176#ifdef WLAN_FEATURE_P2P
2177 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2178 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
2179#endif
2180 hdd_set_conparam(0);
2181 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002182 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2183 hdd_set_station_ops( pAdapter->dev );
2184 status = hdd_init_station_mode( pAdapter );
2185 if( VOS_STATUS_SUCCESS != status )
2186 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002187 /* In case of JB, for P2P-GO, only change interface will be called,
2188 * This is the right place to enable back bmps_imps()
2189 */
2190 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002191 goto done;
2192 case NL80211_IFTYPE_AP:
2193#ifdef WLAN_FEATURE_P2P
2194 case NL80211_IFTYPE_P2P_GO:
2195#endif
2196 wdev->iftype = type;
2197#ifdef WLAN_FEATURE_P2P
2198 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2199 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2200#endif
2201 goto done;
2202 default:
2203 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2204 __func__);
2205 return -EOPNOTSUPP;
2206
2207 }
2208
2209 }
2210 else
2211 {
2212 return -EOPNOTSUPP;
2213 }
2214
2215
2216 if(pRoamProfile)
2217 {
2218 if ( LastBSSType != pRoamProfile->BSSType )
2219 {
2220 /*interface type changed update in wiphy structure*/
2221 wdev->iftype = type;
2222
2223 /*the BSS mode changed, We need to issue disconnect
2224 if connected or in IBSS disconnect state*/
2225 if ( hdd_connGetConnectedBssType(
2226 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2227 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2228 {
2229 /*need to issue a disconnect to CSR.*/
2230 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2231 if( eHAL_STATUS_SUCCESS ==
2232 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2233 pAdapter->sessionId,
2234 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2235 {
2236 wait_for_completion_interruptible_timeout(
2237 &pAdapter->disconnect_comp_var,
2238 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2239 }
2240 }
2241 }
2242 }
2243
2244done:
2245 /*set bitmask based on updated value*/
2246 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
2247#ifdef WLAN_BTAMP_FEATURE
2248 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
2249 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2250 {
2251 //we are ok to do AMP
2252 pHddCtx->isAmpAllowed = VOS_TRUE;
2253 }
2254#endif //WLAN_BTAMP_FEATURE
2255 EXIT();
2256 return 0;
2257}
2258
2259static int wlan_hdd_change_station(struct wiphy *wiphy,
2260 struct net_device *dev,
2261 u8 *mac,
2262 struct station_parameters *params)
2263{
2264 VOS_STATUS status = VOS_STATUS_SUCCESS;
2265 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2266 v_MACADDR_t STAMacAddress;
2267
Jeff Johnsone7245742012-09-05 17:12:55 -07002268 ENTER();
2269
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002270 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2271 {
2272 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2273 "%s:LOGP in Progress. Ignore!!!", __func__);
2274 return -EAGAIN;
2275 }
2276
Jeff Johnson295189b2012-06-20 16:38:30 -07002277 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
2278
2279 if ( ( pAdapter->device_mode == WLAN_HDD_SOFTAP )
2280#ifdef WLAN_FEATURE_P2P
2281 || ( pAdapter->device_mode == WLAN_HDD_P2P_GO )
2282#endif
2283 )
2284 {
2285 if(params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
2286 {
2287 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
2288 WLANTL_STA_AUTHENTICATED);
2289
2290 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
2291 "%s: Station MAC address does not matching", __FUNCTION__);
2292 return -EINVAL;
2293 }
2294 }
2295
Jeff Johnsone7245742012-09-05 17:12:55 -07002296 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002297 return status;
2298}
2299
2300/*
2301 * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
2302 * This function is used to get peer station index in IBSS mode
2303 */
2304static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
2305{
2306 u8 idx = 0;
2307 u8 temp[VOS_MAC_ADDR_SIZE] = {0};
2308 ENTER();
2309 memset(temp, 0, VOS_MAC_ADDR_SIZE);
2310 for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
2311 {
2312 if ( (0 !=
2313 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
2314 && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
2315 temp, VOS_MAC_ADDR_SIZE)
2316 )
2317 {
2318 return idx;
2319 }
2320 }
2321 return idx;
2322}
2323
2324
2325/*
2326 * FUNCTION: wlan_hdd_cfg80211_add_key
2327 * This function is used to initialize the key information
2328 */
2329#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2330static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2331 struct net_device *ndev,
2332 u8 key_index, bool pairwise,
2333 const u8 *mac_addr,
2334 struct key_params *params
2335 )
2336#else
2337static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2338 struct net_device *ndev,
2339 u8 key_index, const u8 *mac_addr,
2340 struct key_params *params
2341 )
2342#endif
2343{
2344 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2345 tCsrRoamSetKey setKey;
2346 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
2347 int status = 0;
2348 v_U32_t roamId= 0xFF;
2349 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2350 hdd_hostapd_state_t *pHostapdState;
2351 VOS_STATUS vos_status;
2352
2353 ENTER();
2354
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002355 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2356 {
2357 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2358 "%s:LOGP in Progress. Ignore!!!", __func__);
2359 return -EAGAIN;
2360 }
2361
Jeff Johnson295189b2012-06-20 16:38:30 -07002362 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2363 __func__,pAdapter->device_mode);
2364
2365 if (CSR_MAX_NUM_KEY <= key_index)
2366 {
2367 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
2368 key_index);
2369
2370 return -EINVAL;
2371 }
2372
2373 hddLog(VOS_TRACE_LEVEL_INFO,
2374 "%s: called with key index = %d & key length %d",
2375 __func__, key_index, params->key_len);
2376
2377 /*extract key idx, key len and key*/
2378 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2379 setKey.keyId = key_index;
2380 setKey.keyLength = params->key_len;
2381 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
2382
2383 switch (params->cipher)
2384 {
2385 case WLAN_CIPHER_SUITE_WEP40:
2386 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
2387 break;
2388
2389 case WLAN_CIPHER_SUITE_WEP104:
2390 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
2391 break;
2392
2393 case WLAN_CIPHER_SUITE_TKIP:
2394 {
2395 u8 *pKey = &setKey.Key[0];
2396 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
2397
2398 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
2399
2400 /*Supplicant sends the 32bytes key in this order
2401
2402 |--------------|----------|----------|
2403 | Tk1 |TX-MIC | RX Mic |
2404 |--------------|----------|----------|
2405 <---16bytes---><--8bytes--><--8bytes-->
2406
2407 */
2408 /*Sme expects the 32 bytes key to be in the below order
2409
2410 |--------------|----------|----------|
2411 | Tk1 |RX-MIC | TX Mic |
2412 |--------------|----------|----------|
2413 <---16bytes---><--8bytes--><--8bytes-->
2414 */
2415 /* Copy the Temporal Key 1 (TK1) */
2416 vos_mem_copy(pKey, params->key,16);
2417
2418 /*Copy the rx mic first*/
2419 vos_mem_copy(&pKey[16],&params->key[24],8);
2420
2421 /*Copy the tx mic */
2422 vos_mem_copy(&pKey[24],&params->key[16],8);
2423
2424
2425 break;
2426 }
2427
2428 case WLAN_CIPHER_SUITE_CCMP:
2429 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
2430 break;
2431
2432#ifdef FEATURE_WLAN_WAPI
2433 case WLAN_CIPHER_SUITE_SMS4:
2434 {
2435 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2436 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
2437 params->key, params->key_len);
2438 return 0;
2439 }
2440#endif
2441#ifdef FEATURE_WLAN_CCX
2442 case WLAN_CIPHER_SUITE_KRK:
2443 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
2444 break;
2445#endif
2446 default:
2447 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
2448 __func__, params->cipher);
2449 return -EOPNOTSUPP;
2450 }
2451
2452 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
2453 __func__, setKey.encType);
2454
2455
2456
2457 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2458#ifdef WLAN_FEATURE_P2P
2459 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2460#endif
2461 )
2462 {
2463
2464
2465 if (
2466#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2467 (!pairwise)
2468#else
2469 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2470#endif
2471 )
2472 {
2473 /* set group key*/
2474 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2475 "%s- %d: setting Broacast key",
2476 __func__, __LINE__);
2477 setKey.keyDirection = eSIR_RX_ONLY;
2478 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2479 }
2480 else
2481 {
2482 /* set pairwise key*/
2483 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2484 "%s- %d: setting pairwise key",
2485 __func__, __LINE__);
2486 setKey.keyDirection = eSIR_TX_RX;
2487 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2488 }
2489
2490 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2491 if( pHostapdState->bssState == BSS_START )
2492 {
2493 status = WLANSAP_SetKeySta( pVosContext, &setKey);
2494
2495 if ( status != eHAL_STATUS_SUCCESS )
2496 {
2497 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2498 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
2499 __LINE__, status );
2500 }
2501 }
2502
2503 /* Saving WEP keys */
2504 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
2505 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
2506 {
2507 //Save the wep key in ap context. Issue setkey after the BSS is started.
2508 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2509 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
2510 }
2511 else
2512 {
2513 //Save the key in ap context. Issue setkey after the BSS is started.
2514 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2515 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
2516 }
2517 }
2518 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2519#ifdef WLAN_FEATURE_P2P
2520 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2521#endif
2522 )
2523 {
2524 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2525 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2526
2527 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
2528
2529 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
2530 params->key, params->key_len);
2531
2532 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
2533
2534 if (!( ( IW_AUTH_KEY_MGMT_802_1X
2535 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2536 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2537 )
2538 &&
2539 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
2540 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
2541 )
2542 )
2543 {
2544 /* in case of static WEP, macaddr/bssid is not coming from nl80211
2545 * interface, copy bssid for pairwise key and group macaddr for
2546 * group key initialization*/
2547
2548 tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
2549
2550 pWextState->roamProfile.negotiatedUCEncryptionType =
2551 pHddStaCtx->conn_info.ucEncryptionType =
2552 ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
2553 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
2554 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
2555
2556
2557 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2558 "%s: Negotiated encryption type %d", __func__,
2559 pWextState->roamProfile.negotiatedUCEncryptionType);
2560
2561 sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
2562 &pWextState->roamProfile, true);
2563 setKey.keyLength = 0;
2564 setKey.keyDirection = eSIR_TX_RX;
2565
2566#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2567 if (pairwise)
2568 {
2569#endif
2570 if (mac_addr)
2571 {
2572 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2573 }
2574 else
2575 {
2576 /* macaddr is NULL, set the peerMac to bssId in case of BSS,
2577 * and peerMacAddress in case of IBSS*/
2578 if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
2579 {
2580 u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
2581 if (HDD_MAX_NUM_IBSS_STA != staidx)
2582 {
2583 vos_mem_copy(setKey.peerMac,
2584 &pHddStaCtx->conn_info.peerMacAddress[staidx],
2585 WNI_CFG_BSSID_LEN);
2586
2587 }
2588 else
2589 {
2590 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
2591 __func__);
2592 return -EOPNOTSUPP;
2593 }
2594 }
2595 else
2596 {
2597 vos_mem_copy(setKey.peerMac,
2598 &pHddStaCtx->conn_info.bssId[0],
2599 WNI_CFG_BSSID_LEN);
2600 }
2601 }
2602#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2603 }
2604 else
2605 {
2606 /* set group key*/
2607 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2608 "%s- %d: setting Group key",
2609 __func__, __LINE__);
2610 setKey.keyDirection = eSIR_RX_ONLY;
2611 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
2612 }
2613#endif
2614 }
2615 else if (
2616#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2617 (!pairwise)
2618#else
2619 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2620#endif
2621 )
2622 {
2623 /* set group key*/
2624 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2625 "%s- %d: setting Group key",
2626 __func__, __LINE__);
2627 setKey.keyDirection = eSIR_RX_ONLY;
2628 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2629 }
2630 else
2631 {
2632 /* set pairwise key*/
2633 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2634 "%s- %d: setting pairwise key",
2635 __func__, __LINE__);
2636 setKey.keyDirection = eSIR_TX_RX;
2637 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2638 }
2639
2640 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2641 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
2642 __func__, setKey.peerMac[0], setKey.peerMac[1],
2643 setKey.peerMac[2], setKey.peerMac[3],
2644 setKey.peerMac[4], setKey.peerMac[5],
2645 setKey.keyDirection);
2646
2647 vos_status = wlan_hdd_check_ula_done(pAdapter);
2648
2649 if ( vos_status != VOS_STATUS_SUCCESS )
2650 {
2651 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2652 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
2653 __LINE__, vos_status );
2654
2655 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2656
2657 return -EINVAL;
2658
2659 }
2660
2661
2662 /* issue set key request to SME*/
2663 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2664 pAdapter->sessionId, &setKey, &roamId );
2665
2666 if ( 0 != status )
2667 {
2668 hddLog(VOS_TRACE_LEVEL_ERROR,
2669 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
2670 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2671 return -EINVAL;
2672 }
2673
2674
2675 /* in case of IBSS as there was no information available about WEP keys during
2676 * IBSS join, group key intialized with NULL key, so re-initialize group key
2677 * with correct value*/
2678 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
2679 !( ( IW_AUTH_KEY_MGMT_802_1X
2680 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2681 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2682 )
2683 &&
2684 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
2685 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
2686 )
2687 )
2688 {
2689 setKey.keyDirection = eSIR_RX_ONLY;
2690 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2691
2692 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2693 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
2694 __func__, setKey.peerMac[0], setKey.peerMac[1],
2695 setKey.peerMac[2], setKey.peerMac[3],
2696 setKey.peerMac[4], setKey.peerMac[5],
2697 setKey.keyDirection);
2698
2699 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2700 pAdapter->sessionId, &setKey, &roamId );
2701
2702 if ( 0 != status )
2703 {
2704 hddLog(VOS_TRACE_LEVEL_ERROR,
2705 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
2706 __func__, status);
2707 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2708 return -EINVAL;
2709 }
2710 }
2711 }
2712
2713 return 0;
2714}
2715
2716/*
2717 * FUNCTION: wlan_hdd_cfg80211_get_key
2718 * This function is used to get the key information
2719 */
2720#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2721static int wlan_hdd_cfg80211_get_key(
2722 struct wiphy *wiphy,
2723 struct net_device *ndev,
2724 u8 key_index, bool pairwise,
2725 const u8 *mac_addr, void *cookie,
2726 void (*callback)(void *cookie, struct key_params*)
2727 )
2728#else
2729static int wlan_hdd_cfg80211_get_key(
2730 struct wiphy *wiphy,
2731 struct net_device *ndev,
2732 u8 key_index, const u8 *mac_addr, void *cookie,
2733 void (*callback)(void *cookie, struct key_params*)
2734 )
2735#endif
2736{
2737 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2738 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2739 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
2740 struct key_params params;
2741
2742 ENTER();
2743
2744 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2745 __func__,pAdapter->device_mode);
2746
2747 memset(&params, 0, sizeof(params));
2748
2749 if (CSR_MAX_NUM_KEY <= key_index)
2750 {
2751 return -EINVAL;
2752 }
2753
2754 switch(pRoamProfile->EncryptionType.encryptionType[0])
2755 {
2756 case eCSR_ENCRYPT_TYPE_NONE:
2757 params.cipher = IW_AUTH_CIPHER_NONE;
2758 break;
2759
2760 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
2761 case eCSR_ENCRYPT_TYPE_WEP40:
2762 params.cipher = WLAN_CIPHER_SUITE_WEP40;
2763 break;
2764
2765 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
2766 case eCSR_ENCRYPT_TYPE_WEP104:
2767 params.cipher = WLAN_CIPHER_SUITE_WEP104;
2768 break;
2769
2770 case eCSR_ENCRYPT_TYPE_TKIP:
2771 params.cipher = WLAN_CIPHER_SUITE_TKIP;
2772 break;
2773
2774 case eCSR_ENCRYPT_TYPE_AES:
2775 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
2776 break;
2777
2778 default:
2779 params.cipher = IW_AUTH_CIPHER_NONE;
2780 break;
2781 }
2782
2783 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
2784 params.seq_len = 0;
2785 params.seq = NULL;
2786 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
2787 callback(cookie, &params);
2788 return 0;
2789}
2790
2791/*
2792 * FUNCTION: wlan_hdd_cfg80211_del_key
2793 * This function is used to delete the key information
2794 */
2795#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2796static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
2797 struct net_device *ndev,
2798 u8 key_index,
2799 bool pairwise,
2800 const u8 *mac_addr
2801 )
2802#else
2803static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
2804 struct net_device *ndev,
2805 u8 key_index,
2806 const u8 *mac_addr
2807 )
2808#endif
2809{
2810 int status = 0;
2811
2812 //This code needs to be revisited. There is sme_removeKey API, we should
2813 //plan to use that. After the change to use correct index in setkey,
2814 //it is observed that this is invalidating peer
2815 //key index whenever re-key is done. This is affecting data link.
2816 //It should be ok to ignore del_key.
2817#if 0
2818 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2819 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2820 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
2821 tCsrRoamSetKey setKey;
2822 v_U32_t roamId= 0xFF;
2823
2824 ENTER();
2825
2826 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
2827 __func__,pAdapter->device_mode);
2828
2829 if (CSR_MAX_NUM_KEY <= key_index)
2830 {
2831 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
2832 key_index);
2833
2834 return -EINVAL;
2835 }
2836
2837 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2838 setKey.keyId = key_index;
2839
2840 if (mac_addr)
2841 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2842 else
2843 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
2844
2845 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
2846
2847 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2848#ifdef WLAN_FEATURE_P2P
2849 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2850#endif
2851 )
2852 {
2853
2854 hdd_hostapd_state_t *pHostapdState =
2855 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2856 if( pHostapdState->bssState == BSS_START)
2857 {
2858 status = WLANSAP_SetKeySta( pVosContext, &setKey);
2859
2860 if ( status != eHAL_STATUS_SUCCESS )
2861 {
2862 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2863 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
2864 __LINE__, status );
2865 }
2866 }
2867 }
2868 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2869#ifdef WLAN_FEATURE_P2P
2870 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2871#endif
2872 )
2873 {
2874 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2875
2876 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
2877
2878 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2879 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
2880 __func__, setKey.peerMac[0], setKey.peerMac[1],
2881 setKey.peerMac[2], setKey.peerMac[3],
2882 setKey.peerMac[4], setKey.peerMac[5]);
2883 if(pAdapter->sessionCtx.station.conn_info.connState ==
2884 eConnectionState_Associated)
2885 {
2886 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2887 pAdapter->sessionId, &setKey, &roamId );
2888
2889 if ( 0 != status )
2890 {
2891 hddLog(VOS_TRACE_LEVEL_ERROR,
2892 "%s: sme_RoamSetKey failure, returned %d",
2893 __func__, status);
2894 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2895 return -EINVAL;
2896 }
2897 }
2898 }
2899#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07002900 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002901 return status;
2902}
2903
2904/*
2905 * FUNCTION: wlan_hdd_cfg80211_set_default_key
2906 * This function is used to set the default tx key index
2907 */
2908#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2909static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
2910 struct net_device *ndev,
2911 u8 key_index,
2912 bool unicast, bool multicast)
2913#else
2914static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
2915 struct net_device *ndev,
2916 u8 key_index)
2917#endif
2918{
2919 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2920 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2921 int status = 0;
2922 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2923
2924 ENTER();
2925
2926 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
2927 __func__,pAdapter->device_mode, key_index);
2928
2929 if (CSR_MAX_NUM_KEY <= key_index)
2930 {
2931 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
2932 key_index);
2933
2934 return -EINVAL;
2935 }
2936
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002937 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2938 {
2939 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2940 "%s:LOGP in Progress. Ignore!!!", __func__);
2941 return -EAGAIN;
2942 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002943
2944 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2945#ifdef WLAN_FEATURE_P2P
2946 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2947#endif
2948 )
2949 {
2950 if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
2951 (eCSR_ENCRYPT_TYPE_TKIP !=
2952 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
2953 (eCSR_ENCRYPT_TYPE_AES !=
2954 pWextState->roamProfile.EncryptionType.encryptionType[0])
2955 )
2956 {
2957 /* if default key index is not same as previous one,
2958 * then update the default key index */
2959
2960 tCsrRoamSetKey setKey;
2961 v_U32_t roamId= 0xFF;
2962 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
2963
2964 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
2965 __func__, key_index);
2966
2967 Keys->defaultIndex = (u8)key_index;
2968 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2969 setKey.keyId = key_index;
2970 setKey.keyLength = Keys->KeyLength[key_index];
2971
2972 vos_mem_copy(&setKey.Key[0],
2973 &Keys->KeyMaterial[key_index][0],
2974 Keys->KeyLength[key_index]);
2975
2976 setKey.keyDirection = eSIR_TX_ONLY;
2977
2978 vos_mem_copy(setKey.peerMac,
2979 &pHddStaCtx->conn_info.bssId[0],
2980 WNI_CFG_BSSID_LEN);
2981
2982 setKey.encType =
2983 pWextState->roamProfile.EncryptionType.encryptionType[0];
2984
2985 /* issue set key request */
2986 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2987 pAdapter->sessionId, &setKey, &roamId );
2988
2989 if ( 0 != status )
2990 {
2991 hddLog(VOS_TRACE_LEVEL_ERROR,
2992 "%s: sme_RoamSetKey failed, returned %d", __func__,
2993 status);
2994 return -EINVAL;
2995 }
2996 }
2997 }
2998
2999 /* In SoftAp mode setting key direction for default mode */
3000 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3001 {
3002 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3003 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3004 (eCSR_ENCRYPT_TYPE_AES !=
3005 pWextState->roamProfile.EncryptionType.encryptionType[0])
3006 )
3007 {
3008 /* Saving key direction for default key index to TX default */
3009 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3010 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3011 }
3012 }
3013
3014 return status;
3015}
3016
3017/**
3018 * FUNCTION: wlan_hdd_cfg80211_set_channel
3019 * This function is used to set the channel number
3020 */
3021int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
3022 struct ieee80211_channel *chan,
3023 enum nl80211_channel_type channel_type
3024 )
3025{
3026 v_U32_t num_ch = 0;
3027 u32 channel = 0;
3028 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
3029 int freq = chan->center_freq; /* freq is in MHZ */
3030
3031 ENTER();
3032
3033 hddLog(VOS_TRACE_LEVEL_INFO,
3034 "%s: device_mode = %d freq = %d \n",__func__,
3035 pAdapter->device_mode, chan->center_freq);
3036
3037 /*
3038 * Do freq to chan conversion
3039 * TODO: for 11a
3040 */
3041
3042 channel = ieee80211_frequency_to_channel(freq);
3043
3044 /* Check freq range */
3045 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
3046 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
3047 {
3048 hddLog(VOS_TRACE_LEVEL_ERROR,
3049 "%s: Channel [%d] is outside valid range from %d to %d\n",
3050 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
3051 WNI_CFG_CURRENT_CHANNEL_STAMAX);
3052 return -EINVAL;
3053 }
3054
3055 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
3056
3057 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode)
3058#ifdef WLAN_FEATURE_P2P
3059 && (WLAN_HDD_P2P_GO != pAdapter->device_mode)
3060#endif
3061 )
3062 {
3063 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
3064 {
3065 hddLog(VOS_TRACE_LEVEL_ERROR,
3066 "%s: Invalid Channel [%d] \n", __func__, channel);
3067 return -EINVAL;
3068 }
3069 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3070 "%s: set channel to [%d] for device mode =%d",
3071 __func__, channel,pAdapter->device_mode);
3072 }
3073 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3074#ifdef WLAN_FEATURE_P2P
3075 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3076#endif
3077 )
3078 {
3079 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3080 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
3081 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3082
3083 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
3084 {
3085 /* Link is up then return cant set channel*/
3086 hddLog( VOS_TRACE_LEVEL_ERROR,
3087 "%s: IBSS Associated, can't set the channel\n", __func__);
3088 return -EINVAL;
3089 }
3090
3091 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
3092 pHddStaCtx->conn_info.operationChannel = channel;
3093 pRoamProfile->ChannelInfo.ChannelList =
3094 &pHddStaCtx->conn_info.operationChannel;
3095 }
3096 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3097#ifdef WLAN_FEATURE_P2P
3098 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
3099#endif
3100 )
3101 {
3102 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
3103
3104 if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3105 {
3106 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3107
3108 /* If auto channel selection is configured as enable/ 1 then ignore
3109 channel set by supplicant
3110 */
3111 if ( cfg_param->apAutoChannelSelection )
3112 {
3113 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = AUTO_CHANNEL_SELECT;
3114
3115 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3116 "%s: set channel to auto channel (0) for device mode =%d",
3117 __func__, pAdapter->device_mode);
3118 }
3119 }
3120 }
3121 else
3122 {
3123 hddLog(VOS_TRACE_LEVEL_FATAL,
3124 "%s: Invalid device mode failed to set valid channel", __func__);
3125 return -EINVAL;
3126 }
3127 EXIT();
3128 return 0;
3129}
3130
3131
3132
3133/*
3134 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3135 * This function is used to inform the BSS details to nl80211 interface.
3136 */
3137static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3138 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3139{
3140 struct net_device *dev = pAdapter->dev;
3141 struct wireless_dev *wdev = dev->ieee80211_ptr;
3142 struct wiphy *wiphy = wdev->wiphy;
3143 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3144 int chan_no;
3145 int ie_length;
3146 const char *ie;
3147 unsigned int freq;
3148 struct ieee80211_channel *chan;
3149 int rssi = 0;
3150 struct cfg80211_bss *bss = NULL;
3151
3152 ENTER();
3153
3154 if( NULL == pBssDesc )
3155 {
3156 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3157 return bss;
3158 }
3159
3160 chan_no = pBssDesc->channelId;
3161 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3162 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3163
3164 if( NULL == ie )
3165 {
3166 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3167 return bss;
3168 }
3169
3170#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3171 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3172 {
3173 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3174 }
3175 else
3176 {
3177 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3178 }
3179#else
3180 freq = ieee80211_channel_to_frequency(chan_no);
3181#endif
3182
3183 chan = __ieee80211_get_channel(wiphy, freq);
3184
3185 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3186 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3187 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3188 if (bss == NULL)
3189 {
3190 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3191
3192 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3193 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3194 pBssDesc->capabilityInfo,
3195 pBssDesc->beaconInterval, ie, ie_length,
3196 rssi, GFP_KERNEL ));
3197}
3198 else
3199 {
3200 return bss;
3201 }
3202}
3203
3204
3205
3206/*
3207 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3208 * This function is used to inform the BSS details to nl80211 interface.
3209 */
3210struct cfg80211_bss*
3211wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3212 tSirBssDescription *bss_desc
3213 )
3214{
3215 /*
3216 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3217 already exists in bss data base of cfg80211 for that particular BSS ID.
3218 Using cfg80211_inform_bss_frame to update the bss entry instead of
3219 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3220 now there is no possibility to get the mgmt(probe response) frame from PE,
3221 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3222 cfg80211_inform_bss_frame.
3223 */
3224 struct net_device *dev = pAdapter->dev;
3225 struct wireless_dev *wdev = dev->ieee80211_ptr;
3226 struct wiphy *wiphy = wdev->wiphy;
3227 int chan_no = bss_desc->channelId;
3228 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
3229 const char *ie =
3230 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3231 unsigned int freq;
3232 struct ieee80211_channel *chan;
3233 struct ieee80211_mgmt *mgmt =
3234 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3235 struct cfg80211_bss *bss_status = NULL;
3236 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3237 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003238#ifdef WLAN_OPEN_SOURCE
3239 struct timespec ts;
3240#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003241
3242 ENTER();
3243
3244 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003245
3246#ifdef WLAN_OPEN_SOURCE
3247 /* Android does not want the timestamp from the frame.
3248 Instead it wants a monotonic increasing value */
3249 get_monotonic_boottime(&ts);
3250 mgmt->u.probe_resp.timestamp =
3251 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3252#else
3253 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003254 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3255 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003256
3257#endif
3258
Jeff Johnson295189b2012-06-20 16:38:30 -07003259 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3260 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
3261 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3262
3263 mgmt->frame_control |=
3264 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3265
3266#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3267 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3268 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3269 {
3270 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3271 }
3272 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3273 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3274
3275 {
3276 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3277 }
3278 else
3279 {
3280 kfree(mgmt);
3281 return NULL;
3282 }
3283#else
3284 freq = ieee80211_channel_to_frequency(chan_no);
3285#endif
3286 chan = __ieee80211_get_channel(wiphy, freq);
3287
3288 /*To keep the rssi icon of the connected AP in the scan window
3289 *and the rssi icon of the wireless networks in sync
3290 * */
3291 if (( eConnectionState_Associated ==
3292 pAdapter->sessionCtx.station.conn_info.connState ) &&
3293 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3294 pAdapter->sessionCtx.station.conn_info.bssId,
3295 WNI_CFG_BSSID_LEN)))
3296 {
3297 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3298 rssi = (pAdapter->rssi * 100);
3299 }
3300 else
3301 {
3302 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3303 }
3304
3305 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3306 frame_len, rssi, GFP_KERNEL);
3307 kfree(mgmt);
3308 return bss_status;
3309}
3310
3311/*
3312 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3313 * This function is used to update the BSS data base of CFG8011
3314 */
3315struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3316 tCsrRoamInfo *pRoamInfo
3317 )
3318{
3319 tCsrRoamConnectedProfile roamProfile;
3320 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3321 struct cfg80211_bss *bss = NULL;
3322
3323 ENTER();
3324
3325 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
3326 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
3327
3328 if (NULL != roamProfile.pBssDesc)
3329 {
3330 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
3331 &roamProfile);
3332
3333 if (NULL == bss)
3334 {
3335 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
3336 __func__);
3337 }
3338
3339 sme_RoamFreeConnectProfile(hHal, &roamProfile);
3340 }
3341 else
3342 {
3343 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
3344 __func__);
3345 }
3346 return bss;
3347}
3348
3349/*
3350 * FUNCTION: wlan_hdd_cfg80211_update_bss
3351 */
3352static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
3353 hdd_adapter_t *pAdapter
3354 )
3355{
3356 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3357 tCsrScanResultInfo *pScanResult;
3358 eHalStatus status = 0;
3359 tScanResultHandle pResult;
3360 struct cfg80211_bss *bss_status = NULL;
3361
3362 ENTER();
3363
3364 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3365 {
3366 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3367 return -EAGAIN;
3368 }
3369
3370 /*
3371 * start getting scan results and populate cgf80211 BSS database
3372 */
3373 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
3374
3375 /* no scan results */
3376 if (NULL == pResult)
3377 {
3378 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
3379 return status;
3380 }
3381
3382 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
3383
3384 while (pScanResult)
3385 {
3386 /*
3387 * cfg80211_inform_bss() is not updating ie field of bss entry, if
3388 * entry already exists in bss data base of cfg80211 for that
3389 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
3390 * bss entry instead of cfg80211_inform_bss, But this call expects
3391 * mgmt packet as input. As of now there is no possibility to get
3392 * the mgmt(probe response) frame from PE, converting bss_desc to
3393 * ieee80211_mgmt(probe response) and passing to c
3394 * fg80211_inform_bss_frame.
3395 * */
3396
3397 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
3398 &pScanResult->BssDescriptor);
3399
3400
3401 if (NULL == bss_status)
3402 {
3403 hddLog(VOS_TRACE_LEVEL_INFO,
3404 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
3405 }
3406 else
3407 {
3408 cfg80211_put_bss(bss_status);
3409 }
3410
3411 pScanResult = sme_ScanResultGetNext(hHal, pResult);
3412 }
3413
3414 sme_ScanResultPurge(hHal, pResult);
3415
3416 return 0;
3417}
3418
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003419void
3420hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
3421{
3422 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003423 "%02X:%02X:%02X:%02X:%02X:%02X\n",
3424 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
3425 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003426} /****** end hddPrintMacAddr() ******/
3427
3428void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003429hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003430{
3431 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003432 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
3433 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
3434 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
3435 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003436} /****** end hddPrintPmkId() ******/
3437
3438//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
3439//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
3440
3441//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
3442//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
3443
3444#define dump_bssid(bssid) \
3445 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003446 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
3447 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
3448 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003449 }
3450
3451#define dump_pmkid(pMac, pmkid) \
3452 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003453 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
3454 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
3455 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003456 }
3457
3458#ifdef FEATURE_WLAN_LFR
3459/*
3460 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
3461 * This function is used to notify the supplicant of a new PMKSA candidate.
3462 */
3463int wlan_hdd_cfg80211_pmksa_candidate_notify(
3464 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
3465 int index, bool preauth )
3466{
Jeff Johnsone7245742012-09-05 17:12:55 -07003467#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003468 struct net_device *dev = pAdapter->dev;
3469
3470 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07003471 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003472
3473 if( NULL == pRoamInfo )
3474 {
3475 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
3476 return -EINVAL;
3477 }
3478
3479 dump_bssid(pRoamInfo->bssid);
3480 cfg80211_pmksa_candidate_notify(dev, index,
3481 pRoamInfo->bssid, preauth, GFP_KERNEL);
Jeff Johnsone7245742012-09-05 17:12:55 -07003482#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003483 return 0;
3484}
3485#endif //FEATURE_WLAN_LFR
3486
Jeff Johnson295189b2012-06-20 16:38:30 -07003487/*
3488 * FUNCTION: hdd_cfg80211_scan_done_callback
3489 * scanning callback function, called after finishing scan
3490 *
3491 */
3492static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
3493 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
3494{
3495 struct net_device *dev = (struct net_device *) pContext;
3496 //struct wireless_dev *wdev = dev->ieee80211_ptr;
3497 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003498 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3499 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07003500 struct cfg80211_scan_request *req = NULL;
3501 int ret = 0;
3502
3503 ENTER();
3504
3505 hddLog(VOS_TRACE_LEVEL_INFO,
3506 "%s called with halHandle = %p, pContext = %p,"
3507 "scanID = %d, returned status = %d\n",
3508 __func__, halHandle, pContext, (int) scanId, (int) status);
3509
3510 //Block on scan req completion variable. Can't wait forever though.
3511 ret = wait_for_completion_interruptible_timeout(
3512 &pScanInfo->scan_req_completion_event,
3513 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
3514 if (!ret)
3515 {
3516 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003517 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003518 }
3519
3520 if(pScanInfo->mScanPending != VOS_TRUE)
3521 {
3522 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003523 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003524 }
3525
3526 /* Check the scanId */
3527 if (pScanInfo->scanId != scanId)
3528 {
3529 hddLog(VOS_TRACE_LEVEL_INFO,
3530 "%s called with mismatched scanId pScanInfo->scanId = %d "
3531 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
3532 (int) scanId);
3533 }
3534
Jeff Johnson295189b2012-06-20 16:38:30 -07003535 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
3536 pAdapter);
3537
3538 if (0 > ret)
3539 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
3540
3541
3542 /* If any client wait scan result through WEXT
3543 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003544 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07003545 {
3546 /* The other scan request waiting for current scan finish
3547 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003548 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003549 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003550 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003551 }
3552 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003553 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003554 {
3555 struct net_device *dev = pAdapter->dev;
3556 union iwreq_data wrqu;
3557 int we_event;
3558 char *msg;
3559
3560 memset(&wrqu, '\0', sizeof(wrqu));
3561 we_event = SIOCGIWSCAN;
3562 msg = NULL;
3563 wireless_send_event(dev, we_event, &wrqu, msg);
3564 }
3565 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003566 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003567
3568 /* Get the Scan Req */
3569 req = pAdapter->request;
3570
3571 if (!req)
3572 {
3573 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003574 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07003575 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003576 }
3577
3578 /*
3579 * setting up 0, just in case.
3580 */
3581 req->n_ssids = 0;
3582 req->n_channels = 0;
3583 req->ie = 0;
3584
Jeff Johnson295189b2012-06-20 16:38:30 -07003585 complete(&pAdapter->abortscan_event_var);
3586 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003587 /* Scan is no longer pending */
3588 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003589
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07003590 /*
3591 * cfg80211_scan_done informing NL80211 about completion
3592 * of scanning
3593 */
3594 cfg80211_scan_done(req, false);
Jeff Johnson295189b2012-06-20 16:38:30 -07003595#ifdef WLAN_FEATURE_P2P
3596 /* Flush out scan result after p2p_serach is done */
Jeff Johnsone7245742012-09-05 17:12:55 -07003597 if(pScanInfo->flushP2pScanResults)
Jeff Johnson295189b2012-06-20 16:38:30 -07003598 {
3599 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -07003600 sme_ScanFlushResult(WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId);
Jeff Johnsone7245742012-09-05 17:12:55 -07003601 pScanInfo->flushP2pScanResults = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003602 }
3603#endif
3604
Jeff Johnsone7245742012-09-05 17:12:55 -07003605allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003606 /* release the wake lock at the end of the scan*/
3607 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07003608
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003609 /* Acquire wakelock to handle the case where APP's tries to suspend
3610 * immediatly after the driver gets connect request(i.e after scan)
3611 * from supplicant, this result in app's is suspending and not able
3612 * to process the connect request to AP */
3613 hdd_allow_suspend_timeout(100);
3614
Jeff Johnson295189b2012-06-20 16:38:30 -07003615 EXIT();
3616 return 0;
3617}
3618
3619/*
3620 * FUNCTION: wlan_hdd_cfg80211_scan
3621 * this scan respond to scan trigger and update cfg80211 scan database
3622 * later, scan dump command can be used to recieve scan results
3623 */
3624int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, struct net_device *dev,
3625 struct cfg80211_scan_request *request)
3626{
3627 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
3628 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3629 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3630 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3631 tCsrScanRequest scanRequest;
3632 tANI_U8 *channelList = NULL, i;
3633 v_U32_t scanId = 0;
3634 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003635 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07003636#ifdef WLAN_FEATURE_P2P
3637 v_U8_t* pP2pIe = NULL;
3638#endif
3639
3640 ENTER();
3641
3642 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3643 __func__,pAdapter->device_mode);
3644#ifdef WLAN_BTAMP_FEATURE
3645 //Scan not supported when AMP traffic is on.
3646 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
3647 {
3648 hddLog(VOS_TRACE_LEVEL_ERROR,
3649 "%s: No scanning when AMP is on", __func__);
3650 return -EOPNOTSUPP;
3651 }
3652#endif
3653 //Scan on any other interface is not supported.
3654 if( pAdapter->device_mode == WLAN_HDD_SOFTAP )
3655 {
3656 hddLog(VOS_TRACE_LEVEL_ERROR,
3657 "%s: Not scanning on device_mode = %d",
3658 __func__, pAdapter->device_mode);
3659 return -EOPNOTSUPP;
3660 }
3661
3662 if (TRUE == pScanInfo->mScanPending)
3663 {
3664 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
3665 return -EBUSY;
3666 }
3667
3668 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3669 {
3670 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3671 "%s:LOGP in Progress. Ignore!!!", __func__);
3672 return -EAGAIN;
3673 }
3674
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07003675 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
3676 {
3677 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3678 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
3679 return -EAGAIN;
3680 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07003681 //Don't Allow Scan and return busy if Remain On
3682 //Channel and action frame is pending
3683 //Otherwise Cancel Remain On Channel and allow Scan
3684 //If no action frame pending
3685 if(0 != wlan_hdd_check_remain_on_channel(pAdapter))
3686 {
3687 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
3688 return -EBUSY;
3689 }
3690
Jeff Johnson295189b2012-06-20 16:38:30 -07003691 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
3692 {
3693 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
3694 "%s: Aquire lock fail", __func__);
3695 return -EAGAIN;
3696 }
3697 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
3698 {
3699 hddLog(VOS_TRACE_LEVEL_WARN,
3700 "%s: MAX TM Level Scan not allowed", __func__);
3701 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
3702 return -EBUSY;
3703 }
3704 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
3705
3706 vos_mem_zero( &scanRequest, sizeof(scanRequest));
3707
3708 if (NULL != request)
3709 {
3710 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
3711 (int)request->n_ssids);
3712
3713 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
3714 * Becasue of this, driver is assuming that this is not wildcard scan and so
3715 * is not aging out the scan results.
3716 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07003717 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07003718 {
3719 request->n_ssids = 0;
3720 }
3721
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003722 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07003723 {
3724 tCsrSSIDInfo *SsidInfo;
3725 int j;
3726 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
3727 /* Allocate num_ssid tCsrSSIDInfo structure */
3728 SsidInfo = scanRequest.SSIDs.SSIDList =
3729 ( tCsrSSIDInfo *)vos_mem_malloc(
3730 request->n_ssids*sizeof(tCsrSSIDInfo));
3731
3732 if(NULL == scanRequest.SSIDs.SSIDList)
3733 {
3734 hddLog(VOS_TRACE_LEVEL_ERROR,
3735 "memory alloc failed SSIDInfo buffer");
3736 return -ENOMEM;
3737 }
3738
3739 /* copy all the ssid's and their length */
3740 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
3741 {
3742 /* get the ssid length */
3743 SsidInfo->SSID.length = request->ssids[j].ssid_len;
3744 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
3745 SsidInfo->SSID.length);
3746 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
3747 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
3748 j, SsidInfo->SSID.ssId);
3749 }
3750 /* set the scan type to active */
3751 scanRequest.scanType = eSIR_ACTIVE_SCAN;
3752 }
3753 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
3754 {
3755 /* set the scan type to active */
3756 scanRequest.scanType = eSIR_ACTIVE_SCAN;
3757 }
3758 else
3759 {
3760 /*Set the scan type to default type, in this case it is ACTIVE*/
3761 scanRequest.scanType = pScanInfo->scan_mode;
3762 }
3763 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
3764 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
3765 }
3766 else
3767 {
3768 /* set the scan type to active */
3769 scanRequest.scanType = eSIR_ACTIVE_SCAN;
3770 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
3771
3772 /* set min and max channel time to zero */
3773 scanRequest.minChnTime = 0;
3774 scanRequest.maxChnTime = 0;
3775 }
3776
3777 /* set BSSType to default type */
3778 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
3779
3780 /*TODO: scan the requested channels only*/
3781
3782 /*Right now scanning all the channels */
3783 if( request )
3784 {
3785 if( request->n_channels )
3786 {
3787 channelList = vos_mem_malloc( request->n_channels );
3788 if( NULL == channelList )
3789 {
3790 status = -ENOMEM;
3791 goto free_mem;
3792 }
3793
3794 for( i = 0 ; i < request->n_channels ; i++ )
3795 channelList[i] = request->channels[i]->hw_value;
3796 }
3797
3798 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
3799 scanRequest.ChannelInfo.ChannelList = channelList;
3800
3801 /* set requestType to full scan */
3802 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
3803
3804 if( request->ie_len )
3805 {
3806 /* save this for future association (join requires this) */
3807 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
3808 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
3809 pScanInfo->scanAddIE.length = request->ie_len;
3810
3811 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07003812 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
3813 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07003814 )
3815 {
3816 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
3817 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
3818 }
3819
3820 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
3821 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
3822
3823#ifdef WLAN_FEATURE_P2P
3824 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
3825 request->ie_len);
3826 if (pP2pIe != NULL)
3827 {
Jeff Johnsone7245742012-09-05 17:12:55 -07003828 /* no_cck will be set during p2p find to disable 11b rates */
3829 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07003830 {
3831 tANI_U8 sessionId = pAdapter->sessionId;
3832 hddLog(VOS_TRACE_LEVEL_INFO,
3833 "%s: This is a P2P Search", __func__);
3834 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07003835
3836 /* Flush the scan results only for P2P search.
3837 P2P search happens on 3 social channels (1, 6, 11) */
3838 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
3839 {
3840 pScanInfo->flushP2pScanResults = 1;
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07003841 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnsone7245742012-09-05 17:12:55 -07003842 sessionId );
3843 }
3844
3845 /*
3846 Skip Dfs Channel in case of P2P Search
3847 if it is set in ini file
3848 */
3849 if(cfg_param->skipDfsChnlInP2pSearch)
3850 {
3851 scanRequest.skipDfsChnlInP2pSearch = 1;
3852 }
3853 else
3854 {
3855 scanRequest.skipDfsChnlInP2pSearch = 0;
3856 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003857
3858 /* set requestType to P2P Discovery */
3859 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnson295189b2012-06-20 16:38:30 -07003860 }
3861 }
3862#endif
3863 }
3864 }
3865
3866 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
3867
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003868 /* acquire the wakelock to avoid the apps suspend during the scan. To
3869 * address the following issues.
3870 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
3871 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
3872 * for long time, this result in apps running at full power for long time.
3873 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
3874 * be stuck in full power because of resume BMPS
3875 */
3876 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07003877
3878 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07003879 pAdapter->sessionId, &scanRequest, &scanId,
3880 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07003881
Jeff Johnson295189b2012-06-20 16:38:30 -07003882 if (eHAL_STATUS_SUCCESS != status)
3883 {
3884 hddLog(VOS_TRACE_LEVEL_ERROR,
3885 "%s: sme_ScanRequest returned error %d", __func__, status);
3886 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07003887 if(eHAL_STATUS_RESOURCES == status)
3888 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07003889 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 -07003890 status = -EBUSY;
3891 } else {
3892 status = -EIO;
3893 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003894 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07003895 goto free_mem;
3896 }
3897
3898 pScanInfo->mScanPending = TRUE;
3899 pAdapter->request = request;
3900 pScanInfo->scanId = scanId;
3901
3902 complete(&pScanInfo->scan_req_completion_event);
3903
3904free_mem:
3905 if( scanRequest.SSIDs.SSIDList )
3906 {
3907 vos_mem_free(scanRequest.SSIDs.SSIDList);
3908 }
3909
3910 if( channelList )
3911 vos_mem_free( channelList );
3912
3913 EXIT();
3914
3915 return status;
3916}
3917
3918/*
3919 * FUNCTION: wlan_hdd_cfg80211_connect_start
3920 * This function is used to start the association process
3921 */
3922int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07003923 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07003924{
3925 int status = 0;
3926 hdd_wext_state_t *pWextState;
3927 v_U32_t roamId;
3928 tCsrRoamProfile *pRoamProfile;
3929 eMib_dot11DesiredBssType connectedBssType;
3930 eCsrAuthType RSNAuthType;
3931
3932 ENTER();
3933
3934 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3935
3936 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
3937 {
3938 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
3939 return -EINVAL;
3940 }
3941
3942 pRoamProfile = &pWextState->roamProfile;
3943
3944 if (pRoamProfile)
3945 {
Jeff Johnsone7245742012-09-05 17:12:55 -07003946 int ret = 0;
3947 hdd_station_ctx_t *pHddStaCtx;
3948 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3949 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
3950
3951 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
3952 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
3953 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07003954 {
3955 /* Issue disconnect to CSR */
3956 INIT_COMPLETION(pAdapter->disconnect_comp_var);
3957 if( eHAL_STATUS_SUCCESS ==
3958 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
3959 pAdapter->sessionId,
3960 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
3961 {
Jeff Johnsone7245742012-09-05 17:12:55 -07003962 ret = wait_for_completion_interruptible_timeout(
3963 &pAdapter->disconnect_comp_var,
3964 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3965 if (0 == ret)
3966 {
3967 VOS_ASSERT(0);
3968 }
3969 }
3970 }
3971 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
3972 {
3973 ret = wait_for_completion_interruptible_timeout(
3974 &pAdapter->disconnect_comp_var,
3975 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3976 if (0 == ret)
3977 {
3978 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07003979 }
3980 }
3981
3982 if (HDD_WMM_USER_MODE_NO_QOS ==
3983 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
3984 {
3985 /*QoS not enabled in cfg file*/
3986 pRoamProfile->uapsd_mask = 0;
3987 }
3988 else
3989 {
3990 /*QoS enabled, update uapsd mask from cfg file*/
3991 pRoamProfile->uapsd_mask =
3992 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
3993 }
3994
3995 pRoamProfile->SSIDs.numOfSSIDs = 1;
3996 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
3997 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
3998 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
3999 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4000 ssid, ssid_len);
4001
4002 if (bssid)
4003 {
4004 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4005 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4006 WNI_CFG_BSSID_LEN);
4007 /* Save BSSID in seperate variable as well, as RoamProfile
4008 BSSID is getting zeroed out in the association process. And in
4009 case of join failure we should send valid BSSID to supplicant
4010 */
4011 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4012 WNI_CFG_BSSID_LEN);
4013 }
4014
4015 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4016 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4017 {
4018 /*set gen ie*/
4019 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4020 /*set auth*/
4021 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4022 }
4023 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4024 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4025 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4026 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4027 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4028 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4029 )
4030 {
4031 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4032 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4033 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4034 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4035 eCSR_AUTH_TYPE_AUTOSWITCH;
4036 pWextState->roamProfile.AuthType.authType[0] =
4037 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4038 }
4039#ifdef FEATURE_WLAN_WAPI
4040 if (pAdapter->wapi_info.nWapiMode)
4041 {
4042 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __FUNCTION__);
4043 switch (pAdapter->wapi_info.wapiAuthMode)
4044 {
4045 case WAPI_AUTH_MODE_PSK:
4046 {
4047 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __FUNCTION__,
4048 pAdapter->wapi_info.wapiAuthMode);
4049 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4050 break;
4051 }
4052 case WAPI_AUTH_MODE_CERT:
4053 {
4054 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __FUNCTION__,
4055 pAdapter->wapi_info.wapiAuthMode);
4056 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4057 break;
4058 }
4059 } // End of switch
4060 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4061 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4062 {
4063 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __FUNCTION__);
4064 pRoamProfile->AuthType.numEntries = 1;
4065 pRoamProfile->EncryptionType.numEntries = 1;
4066 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4067 pRoamProfile->mcEncryptionType.numEntries = 1;
4068 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4069 }
4070 }
4071#endif /* FEATURE_WLAN_WAPI */
4072 pRoamProfile->csrPersona = pAdapter->device_mode;
4073
Jeff Johnson32d95a32012-09-10 13:15:23 -07004074 if( operatingChannel )
4075 {
4076 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4077 pRoamProfile->ChannelInfo.numOfChannels = 1;
4078 }
4079
Jeff Johnson295189b2012-06-20 16:38:30 -07004080 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4081 pAdapter->sessionId, pRoamProfile, &roamId);
4082
Jeff Johnson32d95a32012-09-10 13:15:23 -07004083 pRoamProfile->ChannelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004084 pRoamProfile->ChannelInfo.numOfChannels = 0;
4085 }
4086 else
4087 {
4088 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4089 return -EINVAL;
4090 }
4091 EXIT();
4092 return status;
4093}
4094
4095/*
4096 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4097 * This function is used to set the authentication type (OPEN/SHARED).
4098 *
4099 */
4100static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4101 enum nl80211_auth_type auth_type)
4102{
4103 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4104 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4105
4106 ENTER();
4107
4108 /*set authentication type*/
4109 switch (auth_type)
4110 {
4111 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4112 case NL80211_AUTHTYPE_AUTOMATIC:
4113 hddLog(VOS_TRACE_LEVEL_INFO,
4114 "%s: set authentication type to OPEN", __func__);
4115 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4116 break;
4117
4118 case NL80211_AUTHTYPE_SHARED_KEY:
4119 hddLog(VOS_TRACE_LEVEL_INFO,
4120 "%s: set authentication type to SHARED", __func__);
4121 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4122 break;
4123#ifdef FEATURE_WLAN_CCX
4124 case NL80211_AUTHTYPE_NETWORK_EAP:
4125 hddLog(VOS_TRACE_LEVEL_INFO,
4126 "%s: set authentication type to CCKM WPA", __func__);
4127 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4128 break;
4129#endif
4130
4131
4132 default:
4133 hddLog(VOS_TRACE_LEVEL_ERROR,
4134 "%s: Unsupported authentication type %d", __func__,
4135 auth_type);
4136 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4137 return -EINVAL;
4138 }
4139
4140 pWextState->roamProfile.AuthType.authType[0] =
4141 pHddStaCtx->conn_info.authType;
4142 return 0;
4143}
4144
4145/*
4146 * FUNCTION: wlan_hdd_set_akm_suite
4147 * This function is used to set the key mgmt type(PSK/8021x).
4148 *
4149 */
4150static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
4151 u32 key_mgmt
4152 )
4153{
4154 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4155 ENTER();
4156
4157 /*set key mgmt type*/
4158 switch(key_mgmt)
4159 {
4160 case WLAN_AKM_SUITE_PSK:
4161 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
4162 __func__);
4163 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
4164 break;
4165
4166 case WLAN_AKM_SUITE_8021X:
4167 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
4168 __func__);
4169 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
4170 break;
4171#ifdef FEATURE_WLAN_CCX
4172#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
4173#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
4174 case WLAN_AKM_SUITE_CCKM:
4175 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
4176 __func__);
4177 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
4178 break;
4179#endif
4180
4181 default:
4182 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
4183 __func__, key_mgmt);
4184 return -EINVAL;
4185
4186 }
4187 return 0;
4188}
4189
4190/*
4191 * FUNCTION: wlan_hdd_cfg80211_set_cipher
4192 * This function is used to set the encryption type
4193 * (NONE/WEP40/WEP104/TKIP/CCMP).
4194 */
4195static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
4196 u32 cipher,
4197 bool ucast
4198 )
4199{
4200 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4201 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4202 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4203
4204 ENTER();
4205
4206 if (!cipher)
4207 {
4208 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
4209 __func__, cipher);
4210 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4211 }
4212 else
4213 {
4214
4215 /*set encryption method*/
4216 switch (cipher)
4217 {
4218 case IW_AUTH_CIPHER_NONE:
4219 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4220 break;
4221
4222 case WLAN_CIPHER_SUITE_WEP40:
4223 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4224 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4225 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
4226 else
4227 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4228 break;
4229
4230 case WLAN_CIPHER_SUITE_WEP104:
4231 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4232 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4233 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
4234 else
4235 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
4236 break;
4237
4238 case WLAN_CIPHER_SUITE_TKIP:
4239 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
4240 break;
4241
4242 case WLAN_CIPHER_SUITE_CCMP:
4243 encryptionType = eCSR_ENCRYPT_TYPE_AES;
4244 break;
4245#ifdef FEATURE_WLAN_WAPI
4246 case WLAN_CIPHER_SUITE_SMS4:
4247 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
4248 break;
4249#endif
4250
4251#ifdef FEATURE_WLAN_CCX
4252 case WLAN_CIPHER_SUITE_KRK:
4253 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
4254 break;
4255#endif
4256 default:
4257 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
4258 __func__, cipher);
4259 return -EOPNOTSUPP;
4260 }
4261 }
4262
4263 if (ucast)
4264 {
4265 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
4266 __func__, encryptionType);
4267 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
4268 pWextState->roamProfile.EncryptionType.numEntries = 1;
4269 pWextState->roamProfile.EncryptionType.encryptionType[0] =
4270 encryptionType;
4271 }
4272 else
4273 {
4274 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
4275 __func__, encryptionType);
4276 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
4277 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
4278 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
4279 }
4280
4281 return 0;
4282}
4283
4284
4285/*
4286 * FUNCTION: wlan_hdd_cfg80211_set_ie
4287 * This function is used to parse WPA/RSN IE's.
4288 */
4289int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
4290 u8 *ie,
4291 size_t ie_len
4292 )
4293{
4294 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4295 u8 *genie = ie;
4296 v_U16_t remLen = ie_len;
4297#ifdef FEATURE_WLAN_WAPI
4298 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
4299 u16 *tmp;
4300 v_U16_t akmsuiteCount;
4301 int *akmlist;
4302#endif
4303 ENTER();
4304
4305 /* clear previous assocAddIE */
4306 pWextState->assocAddIE.length = 0;
4307 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
4308
4309 while (remLen >= 2)
4310 {
4311 v_U16_t eLen = 0;
4312 v_U8_t elementId;
4313 elementId = *genie++;
4314 eLen = *genie++;
4315 remLen -= 2;
4316
4317 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
4318 __func__, elementId, eLen);
4319
4320 switch ( elementId )
4321 {
4322 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004323 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 -07004324 {
4325 hddLog(VOS_TRACE_LEVEL_ERROR,
4326 "%s: Invalid WPA IE", __func__);
4327 return -EINVAL;
4328 }
4329 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
4330 {
4331 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4332 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
4333 __func__, eLen + 2);
4334
4335 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4336 {
4337 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE. "
4338 "Need bigger buffer space\n");
4339 VOS_ASSERT(0);
4340 return -ENOMEM;
4341 }
4342 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4343 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4344 pWextState->assocAddIE.length += eLen + 2;
4345
4346 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
4347 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4348 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4349 }
4350 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
4351 {
4352 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
4353 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4354 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
4355 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
4356 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
4357 }
4358#ifdef WLAN_FEATURE_P2P
4359 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
4360 P2P_OUI_TYPE_SIZE))
4361 /*Consider P2P IE, only for P2P Client */
4362 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4363 {
4364 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4365 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
4366 __func__, eLen + 2);
4367
4368 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4369 {
4370 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
4371 "Need bigger buffer space\n");
4372 VOS_ASSERT(0);
4373 return -ENOMEM;
4374 }
4375 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4376 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4377 pWextState->assocAddIE.length += eLen + 2;
4378
4379 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4380 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4381 }
4382#endif
4383#ifdef WLAN_FEATURE_WFD
4384 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
4385 WFD_OUI_TYPE_SIZE))
4386 /*Consider WFD IE, only for P2P Client */
4387 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4388 {
4389 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4390 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
4391 __func__, eLen + 2);
4392
4393 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4394 {
4395 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
4396 "Need bigger buffer space\n");
4397 VOS_ASSERT(0);
4398 return -ENOMEM;
4399 }
4400 // WFD IE is saved to Additional IE ; it should be accumulated to handle
4401 // WPS IE + P2P IE + WFD IE
4402 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4403 pWextState->assocAddIE.length += eLen + 2;
4404
4405 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4406 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4407 }
4408#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004409 /* Appending HS 2.0 Indication Element in Assiciation Request */
4410 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
4411 HS20_OUI_TYPE_SIZE)) )
4412 {
4413 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4414 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
4415 __func__, eLen + 2);
4416
4417 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4418 {
4419 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
4420 "Need bigger buffer space\n");
4421 VOS_ASSERT(0);
4422 return -ENOMEM;
4423 }
4424 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4425 pWextState->assocAddIE.length += eLen + 2;
4426
4427 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4428 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4429 }
4430
Jeff Johnson295189b2012-06-20 16:38:30 -07004431 break;
4432 case DOT11F_EID_RSN:
4433 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN 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.pRSNReqIE = pWextState->WPARSNIE;
4437 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
4438 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004439 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
4440 case DOT11F_EID_EXTCAP:
4441 {
4442 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4443 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
4444 __func__, eLen + 2);
4445
4446 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4447 {
4448 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
4449 "Need bigger buffer space\n");
4450 VOS_ASSERT(0);
4451 return -ENOMEM;
4452 }
4453 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4454 pWextState->assocAddIE.length += eLen + 2;
4455
4456 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4457 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4458 break;
4459 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004460#ifdef FEATURE_WLAN_WAPI
4461 case WLAN_EID_WAPI:
4462 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
4463 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
4464 pAdapter->wapi_info.nWapiMode);
4465 tmp = (u16 *)ie;
4466 tmp = tmp + 2; // Skip element Id and Len, Version
4467 akmsuiteCount = WPA_GET_LE16(tmp);
4468 tmp = tmp + 1;
4469 akmlist = (int *)(tmp);
4470 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
4471 {
4472 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
4473 }
4474 else
4475 {
4476 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
4477 VOS_ASSERT(0);
4478 return -EINVAL;
4479 }
4480
4481 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
4482 {
4483 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
4484 __FUNCTION__);
4485 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
4486 }
4487 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
4488 {
4489 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
4490 __FUNCTION__);
4491 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
4492 }
4493 break;
4494#endif
4495 default:
4496 hddLog (VOS_TRACE_LEVEL_ERROR,
4497 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004498 /* when Unknown IE is received we should break and continue
4499 * to the next IE in the buffer instead we were returning
4500 * so changing this to break */
4501 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07004502 }
4503 genie += eLen;
4504 remLen -= eLen;
4505 }
4506 EXIT();
4507 return 0;
4508}
4509
4510/*
4511 * FUNCTION: wlan_hdd_cfg80211_set_privacy
4512 * This function is used to initialize the security
4513 * parameters during connect operation.
4514 */
4515int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
4516 struct cfg80211_connect_params *req
4517 )
4518{
4519 int status = 0;
4520 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4521 ENTER();
4522
4523 /*set wpa version*/
4524 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
4525
4526 if (req->crypto.wpa_versions)
4527 {
4528 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
4529 && ( (req->ie_len)
4530 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
4531 // Make sure that it is including a WPA IE.
4532 /* Currently NL is putting WPA version 1 even for open,
4533 * since p2p ie is also put in same buffer.
4534 * */
4535 {
4536 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
4537 }
4538 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
4539 {
4540 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
4541 }
4542 }
4543
4544 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
4545 pWextState->wpaVersion);
4546
4547 /*set authentication type*/
4548 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
4549
4550 if (0 > status)
4551 {
4552 hddLog(VOS_TRACE_LEVEL_ERROR,
4553 "%s: failed to set authentication type ", __func__);
4554 return status;
4555 }
4556
4557 /*set key mgmt type*/
4558 if (req->crypto.n_akm_suites)
4559 {
4560 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
4561 if (0 > status)
4562 {
4563 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
4564 __func__);
4565 return status;
4566 }
4567 }
4568
4569 /*set pairwise cipher type*/
4570 if (req->crypto.n_ciphers_pairwise)
4571 {
4572 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
4573 req->crypto.ciphers_pairwise[0], true);
4574 if (0 > status)
4575 {
4576 hddLog(VOS_TRACE_LEVEL_ERROR,
4577 "%s: failed to set unicast cipher type", __func__);
4578 return status;
4579 }
4580 }
4581 else
4582 {
4583 /*Reset previous cipher suite to none*/
4584 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
4585 if (0 > status)
4586 {
4587 hddLog(VOS_TRACE_LEVEL_ERROR,
4588 "%s: failed to set unicast cipher type", __func__);
4589 return status;
4590 }
4591 }
4592
4593 /*set group cipher type*/
4594 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
4595 false);
4596
4597 if (0 > status)
4598 {
4599 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
4600 __func__);
4601 return status;
4602 }
4603
4604 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
4605 if (req->ie_len)
4606 {
4607 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
4608 if ( 0 > status)
4609 {
4610 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
4611 __func__);
4612 return status;
4613 }
4614 }
4615
4616 /*incase of WEP set default key information*/
4617 if (req->key && req->key_len)
4618 {
4619 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
4620 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
4621 )
4622 {
4623 if ( IW_AUTH_KEY_MGMT_802_1X
4624 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
4625 {
4626 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
4627 __func__);
4628 return -EOPNOTSUPP;
4629 }
4630 else
4631 {
4632 u8 key_len = req->key_len;
4633 u8 key_idx = req->key_idx;
4634
4635 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
4636 && (CSR_MAX_NUM_KEY > key_idx)
4637 )
4638 {
4639 hddLog(VOS_TRACE_LEVEL_INFO,
4640 "%s: setting default wep key, key_idx = %hu key_len %hu",
4641 __func__, key_idx, key_len);
4642 vos_mem_copy(
4643 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
4644 req->key, key_len);
4645 pWextState->roamProfile.Keys.KeyLength[key_idx] =
4646 (u8)key_len;
4647 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
4648 }
4649 }
4650 }
4651 }
4652
4653 return status;
4654}
4655
4656/*
4657 * FUNCTION: wlan_hdd_cfg80211_set_privacy
4658 * This function is used to initialize the security
4659 * parameters during connect operation.
4660 */
4661static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
4662 struct net_device *ndev,
4663 struct cfg80211_connect_params *req
4664 )
4665{
4666 int status = 0;
4667 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
4668 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
4669 hdd_context_t *pHddCtx = NULL;
4670
4671 ENTER();
4672
4673 hddLog(VOS_TRACE_LEVEL_INFO,
4674 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
4675
4676 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
4677 {
4678 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4679 "%s:LOGP in Progress. Ignore!!!", __func__);
4680 return -EAGAIN;
4681 }
4682
4683#ifdef WLAN_BTAMP_FEATURE
4684 //Infra connect not supported when AMP traffic is on.
4685 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
4686 {
4687 hddLog(VOS_TRACE_LEVEL_ERROR,
4688 "%s: No connection when AMP is on", __func__);
4689 return -1;
4690 }
4691#endif
4692 /*initialise security parameters*/
4693 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
4694
4695 if ( 0 > status)
4696 {
4697 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
4698 __func__);
4699 return status;
4700 }
4701
4702 //If Device Mode is Station Concurrent Sessions Exit BMps
4703 //P2P Mode will be taken care in Open/close adaptor
4704 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
4705 (vos_concurrent_sessions_running()))
4706 {
4707 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
4708
4709 if (NULL != pVosContext)
4710 {
4711 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
4712 if(NULL != pHddCtx)
4713 {
4714 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
4715 }
4716 }
4717 }
4718
Mohit Khanna765234a2012-09-11 15:08:35 -07004719 if ( req->channel )
4720 {
4721 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
4722 req->ssid_len, req->bssid,
4723 req->channel->hw_value);
4724 }
4725 else
4726 {
4727 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
4728 req->ssid_len, req->bssid,
4729 0);
4730 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004731
4732 if (0 > status)
4733 {
4734 //ReEnable BMPS if disabled
4735 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
4736 (NULL != pHddCtx))
4737 {
4738 //ReEnable Bmps and Imps back
4739 hdd_enable_bmps_imps(pHddCtx);
4740 }
4741
4742 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
4743 return status;
4744 }
4745 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
4746 EXIT();
4747 return status;
4748}
4749
4750
4751/*
4752 * FUNCTION: wlan_hdd_cfg80211_disconnect
4753 * This function is used to issue a disconnect request to SME
4754 */
4755static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
4756 struct net_device *dev,
4757 u16 reason
4758 )
4759{
4760 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4761 tCsrRoamProfile *pRoamProfile =
4762 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
4763 int status = 0;
4764 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4765
4766 ENTER();
4767
4768 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4769 __func__,pAdapter->device_mode);
4770
4771 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
4772 __func__, reason);
4773
4774 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4775 {
4776 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4777 "%s:LOGP in Progress. Ignore!!!",__func__);
4778 return -EAGAIN;
4779 }
4780 if (NULL != pRoamProfile)
4781 {
4782 /*issue disconnect request to SME, if station is in connected state*/
4783 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
4784 {
4785 eCsrRoamDisconnectReason reasonCode =
4786 eCSR_DISCONNECT_REASON_UNSPECIFIED;
4787 switch(reason)
4788 {
4789 case WLAN_REASON_MIC_FAILURE:
4790 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
4791 break;
4792
4793 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
4794 case WLAN_REASON_DISASSOC_AP_BUSY:
4795 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
4796 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
4797 break;
4798
4799 case WLAN_REASON_PREV_AUTH_NOT_VALID:
4800 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
4801 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
4802 break;
4803
4804 case WLAN_REASON_DEAUTH_LEAVING:
4805 default:
4806 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
4807 break;
4808 }
4809 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4810 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
4811 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4812
4813 /*issue disconnect*/
4814 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4815 pAdapter->sessionId, reasonCode);
4816
4817 if ( 0 != status)
4818 {
4819 hddLog(VOS_TRACE_LEVEL_ERROR,
4820 "%s csrRoamDisconnect failure, returned %d \n",
4821 __func__, (int)status );
4822 return -EINVAL;
4823 }
4824
4825 wait_for_completion_interruptible_timeout(
4826 &pAdapter->disconnect_comp_var,
4827 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4828
4829
4830 /*stop tx queues*/
4831 netif_tx_disable(dev);
4832 netif_carrier_off(dev);
4833 }
4834 }
4835 else
4836 {
4837 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
4838 }
4839
4840 return status;
4841}
4842
4843/*
4844 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
4845 * This function is used to initialize the security
4846 * settings in IBSS mode.
4847 */
4848static int wlan_hdd_cfg80211_set_privacy_ibss(
4849 hdd_adapter_t *pAdapter,
4850 struct cfg80211_ibss_params *params
4851 )
4852{
4853 int status = 0;
4854 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4855 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4856 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4857
4858 ENTER();
4859
4860 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
4861
4862 if (params->ie_len && ( NULL != params->ie) )
4863 {
4864 if (WLAN_EID_RSN == params->ie[0])
4865 {
4866 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
4867 encryptionType = eCSR_ENCRYPT_TYPE_AES;
4868 }
4869 else
4870 {
4871 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
4872 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
4873 }
4874 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
4875
4876 if (0 > status)
4877 {
4878 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
4879 __func__);
4880 return status;
4881 }
4882 }
4883
4884 pWextState->roamProfile.AuthType.authType[0] =
4885 pHddStaCtx->conn_info.authType =
4886 eCSR_AUTH_TYPE_OPEN_SYSTEM;
4887
4888 if (params->privacy)
4889 {
4890 /* Security enabled IBSS, At this time there is no information available
4891 * about the security paramters, so initialise the encryption type to
4892 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
4893 * The correct security parameters will be updated later in
4894 * wlan_hdd_cfg80211_add_key */
4895 /* Hal expects encryption type to be set inorder
4896 *enable privacy bit in beacons */
4897
4898 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4899 }
4900
4901 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
4902 pWextState->roamProfile.EncryptionType.numEntries = 1;
4903 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
4904
4905 return status;
4906}
4907
4908/*
4909 * FUNCTION: wlan_hdd_cfg80211_join_ibss
4910 * This function is used to create/join an IBSS
4911 */
4912static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
4913 struct net_device *dev,
4914 struct cfg80211_ibss_params *params
4915 )
4916{
4917 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4918 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4919 tCsrRoamProfile *pRoamProfile;
4920 int status;
4921 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4922
4923 ENTER();
4924
4925 hddLog(VOS_TRACE_LEVEL_INFO,
4926 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
4927
4928 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
4929 {
4930 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4931 "%s:LOGP in Progress. Ignore!!!", __func__);
4932 return -EAGAIN;
4933 }
4934
4935 if (NULL == pWextState)
4936 {
4937 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
4938 __func__);
4939 return -EIO;
4940 }
4941
4942 pRoamProfile = &pWextState->roamProfile;
4943
4944 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
4945 {
4946 hddLog (VOS_TRACE_LEVEL_ERROR,
4947 "%s Interface type is not set to IBSS \n", __func__);
4948 return -EINVAL;
4949 }
4950
4951 /* Set Channel */
4952 if (NULL != params->channel)
4953 {
4954 u8 channelNum;
4955 if (IEEE80211_BAND_5GHZ == params->channel->band)
4956 {
4957 hddLog(VOS_TRACE_LEVEL_ERROR,
4958 "%s: IBSS join is called with unsupported band %d",
4959 __func__, params->channel->band);
4960 return -EOPNOTSUPP;
4961 }
4962
4963 /* Get channel number */
4964 channelNum =
4965 ieee80211_frequency_to_channel(params->channel->center_freq);
4966
4967 /*TODO: use macro*/
4968 if (14 >= channelNum)
4969 {
4970 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
4971 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
4972 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4973 int indx;
4974
4975 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
4976 validChan, &numChans))
4977 {
4978 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
4979 __func__);
4980 return -EOPNOTSUPP;
4981 }
4982
4983 for (indx = 0; indx < numChans; indx++)
4984 {
4985 if (channelNum == validChan[indx])
4986 {
4987 break;
4988 }
4989 }
4990 if (indx >= numChans)
4991 {
4992 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
4993 __func__, channelNum);
4994 return -EINVAL;
4995 }
4996 /* Set the Operational Channel */
4997 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
4998 channelNum);
4999 pRoamProfile->ChannelInfo.numOfChannels = 1;
5000 pHddStaCtx->conn_info.operationChannel = channelNum;
5001 pRoamProfile->ChannelInfo.ChannelList =
5002 &pHddStaCtx->conn_info.operationChannel;
5003 }
5004 else
5005 {
5006 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5007 __func__, channelNum);
5008 return -EINVAL;
5009 }
5010 }
5011
5012 /* Initialize security parameters */
5013 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5014 if (status < 0)
5015 {
5016 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5017 __func__);
5018 return status;
5019 }
5020
5021 /* Issue connect start */
5022 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005023 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005024
5025 if (0 > status)
5026 {
5027 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5028 return status;
5029 }
5030
5031 return 0;
5032}
5033
5034/*
5035 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5036 * This function is used to leave an IBSS
5037 */
5038static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5039 struct net_device *dev
5040 )
5041{
5042 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5043 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5044 tCsrRoamProfile *pRoamProfile;
5045
5046 ENTER();
5047
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005048 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5049 {
5050 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5051 "%s:LOGP in Progress. Ignore!!!", __func__);
5052 return -EAGAIN;
5053 }
5054
Jeff Johnson295189b2012-06-20 16:38:30 -07005055 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5056 if (NULL == pWextState)
5057 {
5058 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5059 __func__);
5060 return -EIO;
5061 }
5062
5063 pRoamProfile = &pWextState->roamProfile;
5064
5065 /* Issue disconnect only if interface type is set to IBSS */
5066 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5067 {
5068 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5069 __func__);
5070 return -EINVAL;
5071 }
5072
5073 /* Issue Disconnect request */
5074 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5075 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5076 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5077
5078 return 0;
5079}
5080
5081/*
5082 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5083 * This function is used to set the phy parameters
5084 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5085 */
5086static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5087 u32 changed)
5088{
5089 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5090 tHalHandle hHal = pHddCtx->hHal;
5091
5092 ENTER();
5093
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005094 if ( pHddCtx->isLogpInProgress )
5095 {
5096 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5097 "%s:LOGP in Progress. Ignore!!!", __func__);
5098 return -EAGAIN;
5099 }
5100
Jeff Johnson295189b2012-06-20 16:38:30 -07005101 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
5102 {
5103 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
5104 WNI_CFG_RTS_THRESHOLD_STAMAX :
5105 wiphy->rts_threshold;
5106
5107 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
5108 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
5109 {
5110 hddLog(VOS_TRACE_LEVEL_ERROR,
5111 "%s: Invalid RTS Threshold value %hu",
5112 __func__, rts_threshold);
5113 return -EINVAL;
5114 }
5115
5116 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
5117 rts_threshold, ccmCfgSetCallback,
5118 eANI_BOOLEAN_TRUE))
5119 {
5120 hddLog(VOS_TRACE_LEVEL_ERROR,
5121 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
5122 __func__, rts_threshold);
5123 return -EIO;
5124 }
5125
5126 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
5127 rts_threshold);
5128 }
5129
5130 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
5131 {
5132 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
5133 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
5134 wiphy->frag_threshold;
5135
5136 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
5137 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
5138 {
5139 hddLog(VOS_TRACE_LEVEL_ERROR,
5140 "%s: Invalid frag_threshold value %hu", __func__,
5141 frag_threshold);
5142 return -EINVAL;
5143 }
5144
5145 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
5146 frag_threshold, ccmCfgSetCallback,
5147 eANI_BOOLEAN_TRUE))
5148 {
5149 hddLog(VOS_TRACE_LEVEL_ERROR,
5150 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
5151 __func__, frag_threshold);
5152 return -EIO;
5153 }
5154
5155 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
5156 frag_threshold);
5157 }
5158
5159 if ((changed & WIPHY_PARAM_RETRY_SHORT)
5160 || (changed & WIPHY_PARAM_RETRY_LONG))
5161 {
5162 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
5163 wiphy->retry_short :
5164 wiphy->retry_long;
5165
5166 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
5167 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
5168 {
5169 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
5170 __func__, retry_value);
5171 return -EINVAL;
5172 }
5173
5174 if (changed & WIPHY_PARAM_RETRY_SHORT)
5175 {
5176 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
5177 retry_value, ccmCfgSetCallback,
5178 eANI_BOOLEAN_TRUE))
5179 {
5180 hddLog(VOS_TRACE_LEVEL_ERROR,
5181 "%s: ccmCfgSetInt failed for long retry count %hu",
5182 __func__, retry_value);
5183 return -EIO;
5184 }
5185 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
5186 __func__, retry_value);
5187 }
5188 else if (changed & WIPHY_PARAM_RETRY_SHORT)
5189 {
5190 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
5191 retry_value, ccmCfgSetCallback,
5192 eANI_BOOLEAN_TRUE))
5193 {
5194 hddLog(VOS_TRACE_LEVEL_ERROR,
5195 "%s: ccmCfgSetInt failed for short retry count %hu",
5196 __func__, retry_value);
5197 return -EIO;
5198 }
5199 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
5200 __func__, retry_value);
5201 }
5202 }
5203
5204 return 0;
5205}
5206
5207/*
5208 * FUNCTION: wlan_hdd_cfg80211_set_txpower
5209 * This function is used to set the txpower
5210 */
5211static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
5212#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
5213 enum tx_power_setting type,
5214#else
5215 enum nl80211_tx_power_setting type,
5216#endif
5217 int dbm)
5218{
5219 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5220 tHalHandle hHal = pHddCtx->hHal;
5221 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5222 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5223
5224 ENTER();
5225
5226 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
5227 dbm, ccmCfgSetCallback,
5228 eANI_BOOLEAN_TRUE))
5229 {
5230 hddLog(VOS_TRACE_LEVEL_ERROR,
5231 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
5232 return -EIO;
5233 }
5234
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005235 if ( pHddCtx->isLogpInProgress )
5236 {
5237 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5238 "%s:LOGP in Progress. Ignore!!!", __func__);
5239 return -EAGAIN;
5240 }
5241
Jeff Johnson295189b2012-06-20 16:38:30 -07005242 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
5243 dbm);
5244
5245 switch(type)
5246 {
5247 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
5248 /* Fall through */
5249 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
5250 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
5251 {
5252 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
5253 __func__);
5254 return -EIO;
5255 }
5256 break;
5257 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
5258 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
5259 __func__);
5260 return -EOPNOTSUPP;
5261 break;
5262 default:
5263 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
5264 __func__, type);
5265 return -EIO;
5266 }
5267
5268 return 0;
5269}
5270
5271/*
5272 * FUNCTION: wlan_hdd_cfg80211_get_txpower
5273 * This function is used to read the txpower
5274 */
5275static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
5276{
5277
5278 hdd_adapter_t *pAdapter;
5279 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5280
Jeff Johnsone7245742012-09-05 17:12:55 -07005281 ENTER();
5282
Jeff Johnson295189b2012-06-20 16:38:30 -07005283 if (NULL == pHddCtx)
5284 {
5285 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
5286 *dbm = 0;
5287 return -ENOENT;
5288 }
5289
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005290 if ( pHddCtx->isLogpInProgress )
5291 {
5292 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5293 "%s:LOGP in Progress. Ignore!!!", __func__);
5294 return -EAGAIN;
5295 }
5296
Jeff Johnson295189b2012-06-20 16:38:30 -07005297 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5298 if (NULL == pAdapter)
5299 {
5300 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
5301 return -ENOENT;
5302 }
5303
5304 wlan_hdd_get_classAstats(pAdapter);
5305 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
5306
Jeff Johnsone7245742012-09-05 17:12:55 -07005307 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005308 return 0;
5309}
5310
5311static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
5312 u8* mac, struct station_info *sinfo)
5313{
5314 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5315 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5316 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
5317 tANI_U8 rate_flags;
5318
5319 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5320 hdd_config_t *pCfg = pHddCtx->cfg_ini;
5321 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5322
5323 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
5324 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
5325 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
5326 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
5327 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
5328 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
5329 tANI_U16 maxRate = 0;
5330 tANI_U16 myRate;
5331 tANI_U16 currentRate = 0;
5332 tANI_U8 maxSpeedMCS = 0;
5333 tANI_U8 maxMCSIdx = 0;
5334 tANI_U8 rateFlag = 1;
5335 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005336 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07005337
Jeff Johnsone7245742012-09-05 17:12:55 -07005338 ENTER();
5339
Jeff Johnson295189b2012-06-20 16:38:30 -07005340 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
5341 (0 == ssidlen))
5342 {
5343 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
5344 " Invalid ssidlen, %d", __func__, ssidlen);
5345 /*To keep GUI happy*/
5346 return 0;
5347 }
5348
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005349 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5350 {
5351 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5352 "%s:LOGP in Progress. Ignore!!!", __func__);
5353 return -EAGAIN;
5354 }
5355
Jeff Johnson295189b2012-06-20 16:38:30 -07005356 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
5357 sinfo->filled |= STATION_INFO_SIGNAL;
5358
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005359 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005360 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
5361
5362 //convert to the UI units of 100kbps
5363 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
5364
5365#ifdef LINKSPEED_DEBUG_ENABLED
5366 pr_info("RSSI %d, RLMS %u, rate %d, rssi high %d, rssi low %d\n",
5367 sinfo->signal,
5368 pCfg->reportMaxLinkSpeed,
5369 myRate,
5370 (int) pCfg->linkSpeedRssiHigh,
5371 (int) pCfg->linkSpeedRssiLow);
5372#endif //LINKSPEED_DEBUG_ENABLED
5373
5374 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
5375 {
5376 // we do not want to necessarily report the current speed
5377 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
5378 {
5379 // report the max possible speed
5380 rssidx = 0;
5381 }
5382 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
5383 {
5384 // report the max possible speed with RSSI scaling
5385 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
5386 {
5387 // report the max possible speed
5388 rssidx = 0;
5389 }
5390 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
5391 {
5392 // report middle speed
5393 rssidx = 1;
5394 }
5395 else
5396 {
5397 // report actual speed
5398 rssidx = 2;
5399 }
5400 }
5401 else
5402 {
5403 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
5404 hddLog(VOS_TRACE_LEVEL_ERROR,
5405 "%s: Invalid value for reportMaxLinkSpeed: %u",
5406 __func__, pCfg->reportMaxLinkSpeed);
5407 rssidx = 0;
5408 }
5409
5410 maxRate = 0;
5411
5412 /* Get Basic Rate Set */
5413 ccmCfgGetStr(hHal, WNI_CFG_OPERATIONAL_RATE_SET, OperationalRates, &ORLeng);
5414 for (i = 0; i < ORLeng; i++)
5415 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005416 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005417 {
5418 /* Validate Rate Set */
5419 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
5420 {
5421 currentRate = supported_data_rate[j].supported_rate[rssidx];
5422 break;
5423 }
5424 }
5425 /* Update MAX rate */
5426 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5427 }
5428
5429 /* Get Extended Rate Set */
5430 ccmCfgGetStr(hHal, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, ExtendedRates, &ERLeng);
5431 for (i = 0; i < ERLeng; i++)
5432 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005433 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005434 {
5435 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
5436 {
5437 currentRate = supported_data_rate[j].supported_rate[rssidx];
5438 break;
5439 }
5440 }
5441 /* Update MAX rate */
5442 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5443 }
5444
5445 /* Get MCS Rate Set -- but only if we are connected at MCS
5446 rates or if we are always reporting max speed or if we have
5447 good rssi */
5448 if ((0 == rssidx) || !(rate_flags & eHAL_TX_RATE_LEGACY))
5449 {
5450 ccmCfgGetStr(hHal, WNI_CFG_CURRENT_MCS_SET, MCSRates, &MCSLeng);
5451 rateFlag = 0;
5452 if (rate_flags & eHAL_TX_RATE_HT40)
5453 {
5454 rateFlag |= 1;
5455 }
5456 if (rate_flags & eHAL_TX_RATE_SGI)
5457 {
5458 rateFlag |= 2;
5459 }
5460
5461 for (i = 0; i < MCSLeng; i++)
5462 {
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005463 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
5464 for (j = 0; j < temp; j++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005465 {
5466 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
5467 {
5468 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
5469 break;
5470 }
5471 }
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005472 if ((j < temp) && (currentRate > maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07005473 {
5474 maxRate = currentRate;
5475 maxSpeedMCS = 1;
5476 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
5477 }
5478 }
5479 }
5480
5481 // make sure we report a value at least as big as our current rate
5482 if (maxRate < myRate)
5483 {
5484 maxRate = myRate;
5485 if (rate_flags & eHAL_TX_RATE_LEGACY)
5486 {
5487 maxSpeedMCS = 0;
5488 }
5489 else
5490 {
5491 maxSpeedMCS = 1;
5492 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
5493 }
5494 }
5495
5496 if (!maxSpeedMCS)
5497 {
5498 sinfo->txrate.legacy = maxRate;
5499#ifdef LINKSPEED_DEBUG_ENABLED
5500 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
5501#endif //LINKSPEED_DEBUG_ENABLED
5502 }
5503 else
5504 {
5505 sinfo->txrate.mcs = maxMCSIdx;
5506 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
5507 if (rate_flags & eHAL_TX_RATE_SGI)
5508 {
5509 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
5510 }
5511 if (rate_flags & eHAL_TX_RATE_HT40)
5512 {
5513 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
5514 }
5515#ifdef LINKSPEED_DEBUG_ENABLED
5516 pr_info("Reporting MCS rate %d flags %x\n",
5517 sinfo->txrate.mcs,
5518 sinfo->txrate.flags );
5519#endif //LINKSPEED_DEBUG_ENABLED
5520 }
5521 }
5522 else
5523 {
5524 // report current rate instead of max rate
5525
5526 if (rate_flags & eHAL_TX_RATE_LEGACY)
5527 {
5528 //provide to the UI in units of 100kbps
5529 sinfo->txrate.legacy = myRate;
5530#ifdef LINKSPEED_DEBUG_ENABLED
5531 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
5532#endif //LINKSPEED_DEBUG_ENABLED
5533 }
5534 else
5535 {
5536 //must be MCS
5537 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
5538 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
5539 if (rate_flags & eHAL_TX_RATE_SGI)
5540 {
5541 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
5542 }
5543 if (rate_flags & eHAL_TX_RATE_HT40)
5544 {
5545 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
5546 }
5547#ifdef LINKSPEED_DEBUG_ENABLED
5548 pr_info("Reporting actual MCS rate %d flags %x\n",
5549 sinfo->txrate.mcs,
5550 sinfo->txrate.flags );
5551#endif //LINKSPEED_DEBUG_ENABLED
5552 }
5553 }
5554 sinfo->filled |= STATION_INFO_TX_BITRATE;
5555
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005556 sinfo->tx_packets =
5557 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
5558 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
5559 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
5560 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
5561
5562 sinfo->tx_retries =
5563 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
5564 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
5565 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
5566 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
5567
5568 sinfo->tx_failed =
5569 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
5570 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
5571 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
5572 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
5573
5574 sinfo->filled |=
5575 STATION_INFO_TX_PACKETS |
5576 STATION_INFO_TX_RETRIES |
5577 STATION_INFO_TX_FAILED;
5578
5579 EXIT();
5580 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005581}
5582
5583static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
5584 struct net_device *dev, bool mode, v_SINT_t timeout)
5585{
5586 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5587 VOS_STATUS vos_status;
5588
Jeff Johnsone7245742012-09-05 17:12:55 -07005589 ENTER();
5590
Jeff Johnson295189b2012-06-20 16:38:30 -07005591 if (NULL == pAdapter)
5592 {
5593 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
5594 return -ENODEV;
5595 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005596 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5597 {
5598 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5599 "%s:LOGP in Progress. Ignore!!!", __func__);
5600 return -EAGAIN;
5601 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005602
5603 /**The get power cmd from the supplicant gets updated by the nl only
5604 *on successful execution of the function call
5605 *we are oppositely mapped w.r.t mode in the driver
5606 **/
5607 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
5608
Jeff Johnsone7245742012-09-05 17:12:55 -07005609 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005610 if (VOS_STATUS_E_FAILURE == vos_status)
5611 {
5612 return -EINVAL;
5613 }
5614 return 0;
5615}
5616
5617
5618#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5619static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
5620 struct net_device *netdev,
5621 u8 key_index)
5622{
Jeff Johnsone7245742012-09-05 17:12:55 -07005623 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005624 return 0;
5625}
5626#endif //LINUX_VERSION_CODE
5627
5628#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
5629static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
5630 struct net_device *dev,
5631 struct ieee80211_txq_params *params)
5632{
Jeff Johnsone7245742012-09-05 17:12:55 -07005633 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005634 return 0;
5635}
5636#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5637static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
5638 struct ieee80211_txq_params *params)
5639{
Jeff Johnsone7245742012-09-05 17:12:55 -07005640 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005641 return 0;
5642}
5643#endif //LINUX_VERSION_CODE
5644
5645static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
5646 struct net_device *dev, u8 *mac)
5647{
5648 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5649
Jeff Johnsone7245742012-09-05 17:12:55 -07005650 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005651 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
5652 {
5653 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
5654 return -EINVAL;
5655 }
5656
5657 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
5658 {
5659 hddLog( LOGE,
5660 "%s: Wlan Load/Unload is in progress", __func__);
5661 return -EBUSY;
5662 }
5663
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005664 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5665 {
5666 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5667 "%s:LOGP in Progress. Ignore!!!", __func__);
5668 return -EAGAIN;
5669 }
5670
Jeff Johnson295189b2012-06-20 16:38:30 -07005671 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
5672#ifdef WLAN_FEATURE_P2P
5673 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
5674#endif
5675 )
5676 {
5677 if( NULL == mac )
5678 {
5679 v_U16_t i;
5680 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
5681 {
5682 if(pAdapter->aStaInfo[i].isUsed)
5683 {
5684 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
5685 hddLog(VOS_TRACE_LEVEL_INFO,
5686 "%s: Delete STA with MAC::"
5687 "%02x:%02x:%02x:%02x:%02x:%02x",
5688 __func__,
5689 macAddr[0], macAddr[1], macAddr[2],
5690 macAddr[3], macAddr[4], macAddr[5]);
5691 hdd_softap_sta_deauth(pAdapter, macAddr);
5692 }
5693 }
5694 }
5695 else
5696 {
5697 hddLog(VOS_TRACE_LEVEL_INFO,
5698 "%s: Delete STA with MAC::"
5699 "%02x:%02x:%02x:%02x:%02x:%02x",
5700 __func__,
5701 mac[0], mac[1], mac[2],
5702 mac[3], mac[4], mac[5]);
5703 hdd_softap_sta_deauth(pAdapter, mac);
5704 }
5705 }
5706
5707 EXIT();
5708
5709 return 0;
5710}
5711
5712static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
5713 struct net_device *dev, u8 *mac, struct station_parameters *params)
5714{
5715 // TODO: Implement this later.
Jeff Johnsone7245742012-09-05 17:12:55 -07005716 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005717 return 0;
5718}
5719
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005720
5721#ifdef FEATURE_WLAN_LFR
5722static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07005723 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005724{
5725#define MAX_PMKSAIDS_IN_CACHE 8
5726 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
5727 static tANI_U32 i = 0; // HDD Local Cache index
5728 tANI_U32 j=0;
5729 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5730 tHalHandle halHandle;
5731 eHalStatus result;
5732 tANI_U8 BSSIDMatched = 0;
5733
Jeff Johnsone7245742012-09-05 17:12:55 -07005734 ENTER();
5735
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005736 // Validate pAdapter
5737 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
5738 {
5739 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
5740 return -EINVAL;
5741 }
5742
5743 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
5744 {
5745 hddLog( LOGE,
5746 "%s: Wlan Load/Unload is in progress", __func__);
5747 return -EBUSY;
5748 }
5749
5750 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5751 {
5752 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5753 "%s:LOGP in Progress. Ignore!!!", __func__);
5754 return -EAGAIN;
5755 }
5756
5757 // Retrieve halHandle
5758 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
5759
5760 for (j = 0; j < i; j++)
5761 {
5762 if(vos_mem_compare(PMKIDCache[j].BSSID,
5763 pmksa->bssid, WNI_CFG_BSSID_LEN))
5764 {
5765 /* BSSID matched previous entry. Overwrite it. */
5766 BSSIDMatched = 1;
5767 vos_mem_copy(PMKIDCache[j].BSSID,
5768 pmksa->bssid, WNI_CFG_BSSID_LEN);
5769 vos_mem_copy(PMKIDCache[j].PMKID,
5770 pmksa->pmkid,
5771 CSR_RSN_PMKID_SIZE);
5772 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
5773 __FUNCTION__, j );
5774 dump_bssid(pmksa->bssid);
5775 dump_pmkid(halHandle, pmksa->pmkid);
5776 break;
5777 }
5778 }
5779
5780 if (!BSSIDMatched)
5781 {
5782 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
5783 vos_mem_copy(PMKIDCache[i].BSSID,
5784 pmksa->bssid, ETHER_ADDR_LEN);
5785 vos_mem_copy(PMKIDCache[i].PMKID,
5786 pmksa->pmkid,
5787 CSR_RSN_PMKID_SIZE);
5788 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
5789 __FUNCTION__, i );
5790 dump_bssid(pmksa->bssid);
5791 dump_pmkid(halHandle, pmksa->pmkid);
5792 // Increment the HDD Local Cache index
5793 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
5794 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
5795 }
5796
5797
5798 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
5799 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
5800 // __FUNCTION__, i );
5801 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
5802 __FUNCTION__, i );
5803 // Finally set the PMKSA ID Cache in CSR
5804 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
5805 PMKIDCache,
5806 i );
5807 return 0;
5808}
5809
5810
5811static int wlan_hdd_cfg80211_del_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{
Jeff Johnsone7245742012-09-05 17:12:55 -07005814 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005815 // TODO: Implement this later.
5816 return 0;
5817}
5818
5819static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
5820{
Jeff Johnsone7245742012-09-05 17:12:55 -07005821 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005822 // TODO: Implement this later.
5823 return 0;
5824}
5825#endif
5826
5827
Jeff Johnson295189b2012-06-20 16:38:30 -07005828/* cfg80211_ops */
5829static struct cfg80211_ops wlan_hdd_cfg80211_ops =
5830{
5831 .add_virtual_intf = wlan_hdd_add_virtual_intf,
5832 .del_virtual_intf = wlan_hdd_del_virtual_intf,
5833 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
5834 .change_station = wlan_hdd_change_station,
5835#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
5836 .add_beacon = wlan_hdd_cfg80211_add_beacon,
5837 .del_beacon = wlan_hdd_cfg80211_del_beacon,
5838 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005839#else
5840 .start_ap = wlan_hdd_cfg80211_start_ap,
5841 .change_beacon = wlan_hdd_cfg80211_change_beacon,
5842 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07005843#endif
5844 .change_bss = wlan_hdd_cfg80211_change_bss,
5845 .add_key = wlan_hdd_cfg80211_add_key,
5846 .get_key = wlan_hdd_cfg80211_get_key,
5847 .del_key = wlan_hdd_cfg80211_del_key,
5848 .set_default_key = wlan_hdd_cfg80211_set_default_key,
5849 .set_channel = wlan_hdd_cfg80211_set_channel,
5850 .scan = wlan_hdd_cfg80211_scan,
5851 .connect = wlan_hdd_cfg80211_connect,
5852 .disconnect = wlan_hdd_cfg80211_disconnect,
5853 .join_ibss = wlan_hdd_cfg80211_join_ibss,
5854 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
5855 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
5856 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
5857 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
5858#ifdef WLAN_FEATURE_P2P
5859 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
5860 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
5861 .mgmt_tx = wlan_hdd_action,
5862#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5863 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
5864 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
5865 .set_txq_params = wlan_hdd_set_txq_params,
5866#endif
5867#endif
5868 .get_station = wlan_hdd_cfg80211_get_station,
5869 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
5870 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005871 .add_station = wlan_hdd_cfg80211_add_station,
5872#ifdef FEATURE_WLAN_LFR
5873 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
5874 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
5875 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
5876#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005877};
5878
5879#endif // CONFIG_CFG80211