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