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