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