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