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