blob: 1b904ff05daa75e65d5c66816b62dc202a3c6f32 [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 );
1920 tCsrRoamProfile *pRoamProfile = NULL;
1921 eCsrRoamBssType LastBSSType;
1922 hdd_config_t *pConfig = pHddCtx->cfg_ini;
1923 eMib_dot11DesiredBssType connectedBssType;
1924 VOS_STATUS status;
1925
1926 ENTER();
1927
1928 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1929 {
1930 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1931 return -EAGAIN;
1932 }
1933
1934 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
1935 __func__, pAdapter->device_mode);
1936
1937 wdev = ndev->ieee80211_ptr;
1938
1939#ifdef WLAN_BTAMP_FEATURE
1940 if((NL80211_IFTYPE_P2P_CLIENT == type)||
1941 (NL80211_IFTYPE_ADHOC == type)||
1942 (NL80211_IFTYPE_AP == type)||
1943 (NL80211_IFTYPE_P2P_GO == type))
1944 {
1945 pHddCtx->isAmpAllowed = VOS_FALSE;
1946 // stop AMP traffic
1947 status = WLANBAP_StopAmp();
1948 if(VOS_STATUS_SUCCESS != status )
1949 {
1950 pHddCtx->isAmpAllowed = VOS_TRUE;
1951 hddLog(VOS_TRACE_LEVEL_FATAL,
1952 "%s: Failed to stop AMP", __func__);
1953 return -EINVAL;
1954 }
1955 }
1956#endif //WLAN_BTAMP_FEATURE
1957 /* Reset the current device mode bit mask*/
1958 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
1959
1960 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
1961#ifdef WLAN_FEATURE_P2P
1962 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07001963 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07001964#endif
1965 )
1966 {
1967 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
1968 pRoamProfile = &pWextState->roamProfile;
1969 LastBSSType = pRoamProfile->BSSType;
1970
1971 switch (type)
1972 {
1973 case NL80211_IFTYPE_STATION:
1974#ifdef WLAN_FEATURE_P2P
1975 case NL80211_IFTYPE_P2P_CLIENT:
1976#endif
1977 hddLog(VOS_TRACE_LEVEL_INFO,
1978 "%s: setting interface Type to INFRASTRUCTURE", __func__);
1979 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07001980#ifdef WLAN_FEATURE_11AC
1981 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
1982 {
1983 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
1984 }
1985#endif
1986 pRoamProfile->phyMode =
1987 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07001988 wdev->iftype = type;
1989#ifdef WLAN_FEATURE_P2P
1990 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
1991 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
1992#endif
1993 break;
1994 case NL80211_IFTYPE_ADHOC:
1995 hddLog(VOS_TRACE_LEVEL_INFO,
1996 "%s: setting interface Type to ADHOC", __func__);
1997 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
1998 pRoamProfile->phyMode =
1999 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
2000 wdev->iftype = type;
2001 break;
2002
2003 case NL80211_IFTYPE_AP:
2004#ifdef WLAN_FEATURE_P2P
2005 case NL80211_IFTYPE_P2P_GO:
2006#endif
2007 {
2008 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2009 "%s: setting interface Type to %s", __func__,
2010 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2011
2012 //De-init the adapter.
2013 hdd_stop_adapter( pHddCtx, pAdapter );
2014 hdd_deinit_adapter( pHddCtx, pAdapter );
2015 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2016#ifdef WLAN_SOFTAP_FEATURE
2017#ifdef WLAN_FEATURE_P2P
2018 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2019 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2020#else
2021 pAdapter->device_mode = WLAN_HDD_SOFTAP;
2022#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07002023
2024 //Disable BMPS and IMPS if enabled
2025 //before starting Go
2026 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2027 {
2028 if(VOS_STATUS_E_FAILURE ==
2029 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2030 {
2031 //Fail to Exit BMPS
2032 VOS_ASSERT(0);
2033 }
2034 }
2035
Jeff Johnson295189b2012-06-20 16:38:30 -07002036 hdd_set_ap_ops( pAdapter->dev );
2037
2038 status = hdd_init_ap_mode(pAdapter);
2039 if(status != VOS_STATUS_SUCCESS)
2040 {
2041 hddLog(VOS_TRACE_LEVEL_FATAL,
2042 "%s: Error initializing the ap mode", __func__);
2043 return -EINVAL;
2044 }
2045 hdd_set_conparam(1);
2046
2047#endif
2048 /*interface type changed update in wiphy structure*/
2049 if(wdev)
2050 {
2051 wdev->iftype = type;
2052 pHddCtx->change_iface = type;
2053 }
2054 else
2055 {
2056 hddLog(VOS_TRACE_LEVEL_ERROR,
2057 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2058 return -EINVAL;
2059 }
2060 goto done;
2061 }
2062
2063 default:
2064 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2065 __func__);
2066 return -EOPNOTSUPP;
2067 }
2068 }
2069 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
2070#ifdef WLAN_FEATURE_P2P
2071 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2072#endif
2073 )
2074 {
2075 switch(type)
2076 {
2077 case NL80211_IFTYPE_STATION:
2078#ifdef WLAN_FEATURE_P2P
2079 case NL80211_IFTYPE_P2P_CLIENT:
2080#endif
2081 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002082 hdd_stop_adapter( pHddCtx, pAdapter );
2083 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002084 wdev->iftype = type;
2085#ifdef WLAN_FEATURE_P2P
2086 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2087 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
2088#endif
2089 hdd_set_conparam(0);
2090 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002091 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2092 hdd_set_station_ops( pAdapter->dev );
2093 status = hdd_init_station_mode( pAdapter );
2094 if( VOS_STATUS_SUCCESS != status )
2095 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002096 /* In case of JB, for P2P-GO, only change interface will be called,
2097 * This is the right place to enable back bmps_imps()
2098 */
2099 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002100 goto done;
2101 case NL80211_IFTYPE_AP:
2102#ifdef WLAN_FEATURE_P2P
2103 case NL80211_IFTYPE_P2P_GO:
2104#endif
2105 wdev->iftype = type;
2106#ifdef WLAN_FEATURE_P2P
2107 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2108 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2109#endif
2110 goto done;
2111 default:
2112 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2113 __func__);
2114 return -EOPNOTSUPP;
2115
2116 }
2117
2118 }
2119 else
2120 {
2121 return -EOPNOTSUPP;
2122 }
2123
2124
2125 if(pRoamProfile)
2126 {
2127 if ( LastBSSType != pRoamProfile->BSSType )
2128 {
2129 /*interface type changed update in wiphy structure*/
2130 wdev->iftype = type;
2131
2132 /*the BSS mode changed, We need to issue disconnect
2133 if connected or in IBSS disconnect state*/
2134 if ( hdd_connGetConnectedBssType(
2135 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2136 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2137 {
2138 /*need to issue a disconnect to CSR.*/
2139 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2140 if( eHAL_STATUS_SUCCESS ==
2141 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2142 pAdapter->sessionId,
2143 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2144 {
2145 wait_for_completion_interruptible_timeout(
2146 &pAdapter->disconnect_comp_var,
2147 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2148 }
2149 }
2150 }
2151 }
2152
2153done:
2154 /*set bitmask based on updated value*/
2155 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
2156#ifdef WLAN_BTAMP_FEATURE
2157 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
2158 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2159 {
2160 //we are ok to do AMP
2161 pHddCtx->isAmpAllowed = VOS_TRUE;
2162 }
2163#endif //WLAN_BTAMP_FEATURE
2164 EXIT();
2165 return 0;
2166}
2167
2168static int wlan_hdd_change_station(struct wiphy *wiphy,
2169 struct net_device *dev,
2170 u8 *mac,
2171 struct station_parameters *params)
2172{
2173 VOS_STATUS status = VOS_STATUS_SUCCESS;
2174 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2175 v_MACADDR_t STAMacAddress;
2176
Jeff Johnsone7245742012-09-05 17:12:55 -07002177 ENTER();
2178
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002179 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2180 {
2181 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2182 "%s:LOGP in Progress. Ignore!!!", __func__);
2183 return -EAGAIN;
2184 }
2185
Jeff Johnson295189b2012-06-20 16:38:30 -07002186 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
2187
2188 if ( ( pAdapter->device_mode == WLAN_HDD_SOFTAP )
2189#ifdef WLAN_FEATURE_P2P
2190 || ( pAdapter->device_mode == WLAN_HDD_P2P_GO )
2191#endif
2192 )
2193 {
2194 if(params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
2195 {
2196 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
2197 WLANTL_STA_AUTHENTICATED);
2198
2199 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
2200 "%s: Station MAC address does not matching", __FUNCTION__);
2201 return -EINVAL;
2202 }
2203 }
2204
Jeff Johnsone7245742012-09-05 17:12:55 -07002205 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002206 return status;
2207}
2208
2209/*
2210 * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
2211 * This function is used to get peer station index in IBSS mode
2212 */
2213static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
2214{
2215 u8 idx = 0;
2216 u8 temp[VOS_MAC_ADDR_SIZE] = {0};
2217 ENTER();
2218 memset(temp, 0, VOS_MAC_ADDR_SIZE);
2219 for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
2220 {
2221 if ( (0 !=
2222 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
2223 && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
2224 temp, VOS_MAC_ADDR_SIZE)
2225 )
2226 {
2227 return idx;
2228 }
2229 }
2230 return idx;
2231}
2232
2233
2234/*
2235 * FUNCTION: wlan_hdd_cfg80211_add_key
2236 * This function is used to initialize the key information
2237 */
2238#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2239static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2240 struct net_device *ndev,
2241 u8 key_index, bool pairwise,
2242 const u8 *mac_addr,
2243 struct key_params *params
2244 )
2245#else
2246static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2247 struct net_device *ndev,
2248 u8 key_index, const u8 *mac_addr,
2249 struct key_params *params
2250 )
2251#endif
2252{
2253 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2254 tCsrRoamSetKey setKey;
2255 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
2256 int status = 0;
2257 v_U32_t roamId= 0xFF;
2258 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2259 hdd_hostapd_state_t *pHostapdState;
2260 VOS_STATUS vos_status;
2261
2262 ENTER();
2263
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002264 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2265 {
2266 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2267 "%s:LOGP in Progress. Ignore!!!", __func__);
2268 return -EAGAIN;
2269 }
2270
Jeff Johnson295189b2012-06-20 16:38:30 -07002271 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2272 __func__,pAdapter->device_mode);
2273
2274 if (CSR_MAX_NUM_KEY <= key_index)
2275 {
2276 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
2277 key_index);
2278
2279 return -EINVAL;
2280 }
2281
2282 hddLog(VOS_TRACE_LEVEL_INFO,
2283 "%s: called with key index = %d & key length %d",
2284 __func__, key_index, params->key_len);
2285
2286 /*extract key idx, key len and key*/
2287 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2288 setKey.keyId = key_index;
2289 setKey.keyLength = params->key_len;
2290 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
2291
2292 switch (params->cipher)
2293 {
2294 case WLAN_CIPHER_SUITE_WEP40:
2295 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
2296 break;
2297
2298 case WLAN_CIPHER_SUITE_WEP104:
2299 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
2300 break;
2301
2302 case WLAN_CIPHER_SUITE_TKIP:
2303 {
2304 u8 *pKey = &setKey.Key[0];
2305 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
2306
2307 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
2308
2309 /*Supplicant sends the 32bytes key in this order
2310
2311 |--------------|----------|----------|
2312 | Tk1 |TX-MIC | RX Mic |
2313 |--------------|----------|----------|
2314 <---16bytes---><--8bytes--><--8bytes-->
2315
2316 */
2317 /*Sme expects the 32 bytes key to be in the below order
2318
2319 |--------------|----------|----------|
2320 | Tk1 |RX-MIC | TX Mic |
2321 |--------------|----------|----------|
2322 <---16bytes---><--8bytes--><--8bytes-->
2323 */
2324 /* Copy the Temporal Key 1 (TK1) */
2325 vos_mem_copy(pKey, params->key,16);
2326
2327 /*Copy the rx mic first*/
2328 vos_mem_copy(&pKey[16],&params->key[24],8);
2329
2330 /*Copy the tx mic */
2331 vos_mem_copy(&pKey[24],&params->key[16],8);
2332
2333
2334 break;
2335 }
2336
2337 case WLAN_CIPHER_SUITE_CCMP:
2338 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
2339 break;
2340
2341#ifdef FEATURE_WLAN_WAPI
2342 case WLAN_CIPHER_SUITE_SMS4:
2343 {
2344 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2345 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
2346 params->key, params->key_len);
2347 return 0;
2348 }
2349#endif
2350#ifdef FEATURE_WLAN_CCX
2351 case WLAN_CIPHER_SUITE_KRK:
2352 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
2353 break;
2354#endif
2355 default:
2356 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
2357 __func__, params->cipher);
2358 return -EOPNOTSUPP;
2359 }
2360
2361 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
2362 __func__, setKey.encType);
2363
2364
2365
2366 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2367#ifdef WLAN_FEATURE_P2P
2368 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2369#endif
2370 )
2371 {
2372
2373
2374 if (
2375#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2376 (!pairwise)
2377#else
2378 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2379#endif
2380 )
2381 {
2382 /* set group key*/
2383 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2384 "%s- %d: setting Broacast key",
2385 __func__, __LINE__);
2386 setKey.keyDirection = eSIR_RX_ONLY;
2387 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2388 }
2389 else
2390 {
2391 /* set pairwise key*/
2392 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2393 "%s- %d: setting pairwise key",
2394 __func__, __LINE__);
2395 setKey.keyDirection = eSIR_TX_RX;
2396 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2397 }
2398
2399 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2400 if( pHostapdState->bssState == BSS_START )
2401 {
2402 status = WLANSAP_SetKeySta( pVosContext, &setKey);
2403
2404 if ( status != eHAL_STATUS_SUCCESS )
2405 {
2406 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2407 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
2408 __LINE__, status );
2409 }
2410 }
2411
2412 /* Saving WEP keys */
2413 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
2414 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
2415 {
2416 //Save the wep key in ap context. Issue setkey after the BSS is started.
2417 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2418 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
2419 }
2420 else
2421 {
2422 //Save the key in ap context. Issue setkey after the BSS is started.
2423 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2424 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
2425 }
2426 }
2427 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2428#ifdef WLAN_FEATURE_P2P
2429 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2430#endif
2431 )
2432 {
2433 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2434 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2435
2436 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
2437
2438 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
2439 params->key, params->key_len);
2440
2441 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
2442
2443 if (!( ( IW_AUTH_KEY_MGMT_802_1X
2444 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2445 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2446 )
2447 &&
2448 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
2449 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
2450 )
2451 )
2452 {
2453 /* in case of static WEP, macaddr/bssid is not coming from nl80211
2454 * interface, copy bssid for pairwise key and group macaddr for
2455 * group key initialization*/
2456
2457 tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
2458
2459 pWextState->roamProfile.negotiatedUCEncryptionType =
2460 pHddStaCtx->conn_info.ucEncryptionType =
2461 ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
2462 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
2463 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
2464
2465
2466 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2467 "%s: Negotiated encryption type %d", __func__,
2468 pWextState->roamProfile.negotiatedUCEncryptionType);
2469
2470 sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
2471 &pWextState->roamProfile, true);
2472 setKey.keyLength = 0;
2473 setKey.keyDirection = eSIR_TX_RX;
2474
2475#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2476 if (pairwise)
2477 {
2478#endif
2479 if (mac_addr)
2480 {
2481 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2482 }
2483 else
2484 {
2485 /* macaddr is NULL, set the peerMac to bssId in case of BSS,
2486 * and peerMacAddress in case of IBSS*/
2487 if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
2488 {
2489 u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
2490 if (HDD_MAX_NUM_IBSS_STA != staidx)
2491 {
2492 vos_mem_copy(setKey.peerMac,
2493 &pHddStaCtx->conn_info.peerMacAddress[staidx],
2494 WNI_CFG_BSSID_LEN);
2495
2496 }
2497 else
2498 {
2499 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
2500 __func__);
2501 return -EOPNOTSUPP;
2502 }
2503 }
2504 else
2505 {
2506 vos_mem_copy(setKey.peerMac,
2507 &pHddStaCtx->conn_info.bssId[0],
2508 WNI_CFG_BSSID_LEN);
2509 }
2510 }
2511#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2512 }
2513 else
2514 {
2515 /* set group key*/
2516 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2517 "%s- %d: setting Group key",
2518 __func__, __LINE__);
2519 setKey.keyDirection = eSIR_RX_ONLY;
2520 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
2521 }
2522#endif
2523 }
2524 else if (
2525#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2526 (!pairwise)
2527#else
2528 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2529#endif
2530 )
2531 {
2532 /* set group key*/
2533 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2534 "%s- %d: setting Group key",
2535 __func__, __LINE__);
2536 setKey.keyDirection = eSIR_RX_ONLY;
2537 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2538 }
2539 else
2540 {
2541 /* set pairwise key*/
2542 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2543 "%s- %d: setting pairwise key",
2544 __func__, __LINE__);
2545 setKey.keyDirection = eSIR_TX_RX;
2546 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2547 }
2548
2549 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2550 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
2551 __func__, setKey.peerMac[0], setKey.peerMac[1],
2552 setKey.peerMac[2], setKey.peerMac[3],
2553 setKey.peerMac[4], setKey.peerMac[5],
2554 setKey.keyDirection);
2555
2556 vos_status = wlan_hdd_check_ula_done(pAdapter);
2557
2558 if ( vos_status != VOS_STATUS_SUCCESS )
2559 {
2560 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2561 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
2562 __LINE__, vos_status );
2563
2564 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2565
2566 return -EINVAL;
2567
2568 }
2569
2570
2571 /* issue set key request to SME*/
2572 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2573 pAdapter->sessionId, &setKey, &roamId );
2574
2575 if ( 0 != status )
2576 {
2577 hddLog(VOS_TRACE_LEVEL_ERROR,
2578 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
2579 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2580 return -EINVAL;
2581 }
2582
2583
2584 /* in case of IBSS as there was no information available about WEP keys during
2585 * IBSS join, group key intialized with NULL key, so re-initialize group key
2586 * with correct value*/
2587 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
2588 !( ( IW_AUTH_KEY_MGMT_802_1X
2589 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2590 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2591 )
2592 &&
2593 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
2594 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
2595 )
2596 )
2597 {
2598 setKey.keyDirection = eSIR_RX_ONLY;
2599 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2600
2601 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2602 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
2603 __func__, setKey.peerMac[0], setKey.peerMac[1],
2604 setKey.peerMac[2], setKey.peerMac[3],
2605 setKey.peerMac[4], setKey.peerMac[5],
2606 setKey.keyDirection);
2607
2608 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2609 pAdapter->sessionId, &setKey, &roamId );
2610
2611 if ( 0 != status )
2612 {
2613 hddLog(VOS_TRACE_LEVEL_ERROR,
2614 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
2615 __func__, status);
2616 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2617 return -EINVAL;
2618 }
2619 }
2620 }
2621
2622 return 0;
2623}
2624
2625/*
2626 * FUNCTION: wlan_hdd_cfg80211_get_key
2627 * This function is used to get the key information
2628 */
2629#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2630static int wlan_hdd_cfg80211_get_key(
2631 struct wiphy *wiphy,
2632 struct net_device *ndev,
2633 u8 key_index, bool pairwise,
2634 const u8 *mac_addr, void *cookie,
2635 void (*callback)(void *cookie, struct key_params*)
2636 )
2637#else
2638static int wlan_hdd_cfg80211_get_key(
2639 struct wiphy *wiphy,
2640 struct net_device *ndev,
2641 u8 key_index, const u8 *mac_addr, void *cookie,
2642 void (*callback)(void *cookie, struct key_params*)
2643 )
2644#endif
2645{
2646 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2647 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2648 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
2649 struct key_params params;
2650
2651 ENTER();
2652
2653 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2654 __func__,pAdapter->device_mode);
2655
2656 memset(&params, 0, sizeof(params));
2657
2658 if (CSR_MAX_NUM_KEY <= key_index)
2659 {
2660 return -EINVAL;
2661 }
2662
2663 switch(pRoamProfile->EncryptionType.encryptionType[0])
2664 {
2665 case eCSR_ENCRYPT_TYPE_NONE:
2666 params.cipher = IW_AUTH_CIPHER_NONE;
2667 break;
2668
2669 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
2670 case eCSR_ENCRYPT_TYPE_WEP40:
2671 params.cipher = WLAN_CIPHER_SUITE_WEP40;
2672 break;
2673
2674 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
2675 case eCSR_ENCRYPT_TYPE_WEP104:
2676 params.cipher = WLAN_CIPHER_SUITE_WEP104;
2677 break;
2678
2679 case eCSR_ENCRYPT_TYPE_TKIP:
2680 params.cipher = WLAN_CIPHER_SUITE_TKIP;
2681 break;
2682
2683 case eCSR_ENCRYPT_TYPE_AES:
2684 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
2685 break;
2686
2687 default:
2688 params.cipher = IW_AUTH_CIPHER_NONE;
2689 break;
2690 }
2691
2692 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
2693 params.seq_len = 0;
2694 params.seq = NULL;
2695 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
2696 callback(cookie, &params);
2697 return 0;
2698}
2699
2700/*
2701 * FUNCTION: wlan_hdd_cfg80211_del_key
2702 * This function is used to delete the key information
2703 */
2704#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2705static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
2706 struct net_device *ndev,
2707 u8 key_index,
2708 bool pairwise,
2709 const u8 *mac_addr
2710 )
2711#else
2712static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
2713 struct net_device *ndev,
2714 u8 key_index,
2715 const u8 *mac_addr
2716 )
2717#endif
2718{
2719 int status = 0;
2720
2721 //This code needs to be revisited. There is sme_removeKey API, we should
2722 //plan to use that. After the change to use correct index in setkey,
2723 //it is observed that this is invalidating peer
2724 //key index whenever re-key is done. This is affecting data link.
2725 //It should be ok to ignore del_key.
2726#if 0
2727 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2728 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2729 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
2730 tCsrRoamSetKey setKey;
2731 v_U32_t roamId= 0xFF;
2732
2733 ENTER();
2734
2735 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
2736 __func__,pAdapter->device_mode);
2737
2738 if (CSR_MAX_NUM_KEY <= key_index)
2739 {
2740 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
2741 key_index);
2742
2743 return -EINVAL;
2744 }
2745
2746 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2747 setKey.keyId = key_index;
2748
2749 if (mac_addr)
2750 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2751 else
2752 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
2753
2754 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
2755
2756 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2757#ifdef WLAN_FEATURE_P2P
2758 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2759#endif
2760 )
2761 {
2762
2763 hdd_hostapd_state_t *pHostapdState =
2764 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2765 if( pHostapdState->bssState == BSS_START)
2766 {
2767 status = WLANSAP_SetKeySta( pVosContext, &setKey);
2768
2769 if ( status != eHAL_STATUS_SUCCESS )
2770 {
2771 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2772 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
2773 __LINE__, status );
2774 }
2775 }
2776 }
2777 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2778#ifdef WLAN_FEATURE_P2P
2779 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2780#endif
2781 )
2782 {
2783 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2784
2785 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
2786
2787 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2788 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
2789 __func__, setKey.peerMac[0], setKey.peerMac[1],
2790 setKey.peerMac[2], setKey.peerMac[3],
2791 setKey.peerMac[4], setKey.peerMac[5]);
2792 if(pAdapter->sessionCtx.station.conn_info.connState ==
2793 eConnectionState_Associated)
2794 {
2795 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2796 pAdapter->sessionId, &setKey, &roamId );
2797
2798 if ( 0 != status )
2799 {
2800 hddLog(VOS_TRACE_LEVEL_ERROR,
2801 "%s: sme_RoamSetKey failure, returned %d",
2802 __func__, status);
2803 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2804 return -EINVAL;
2805 }
2806 }
2807 }
2808#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07002809 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002810 return status;
2811}
2812
2813/*
2814 * FUNCTION: wlan_hdd_cfg80211_set_default_key
2815 * This function is used to set the default tx key index
2816 */
2817#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2818static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
2819 struct net_device *ndev,
2820 u8 key_index,
2821 bool unicast, bool multicast)
2822#else
2823static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
2824 struct net_device *ndev,
2825 u8 key_index)
2826#endif
2827{
2828 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2829 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2830 int status = 0;
2831 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2832
2833 ENTER();
2834
2835 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
2836 __func__,pAdapter->device_mode, key_index);
2837
2838 if (CSR_MAX_NUM_KEY <= key_index)
2839 {
2840 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
2841 key_index);
2842
2843 return -EINVAL;
2844 }
2845
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002846 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2847 {
2848 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2849 "%s:LOGP in Progress. Ignore!!!", __func__);
2850 return -EAGAIN;
2851 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002852
2853 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2854#ifdef WLAN_FEATURE_P2P
2855 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2856#endif
2857 )
2858 {
2859 if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
2860 (eCSR_ENCRYPT_TYPE_TKIP !=
2861 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
2862 (eCSR_ENCRYPT_TYPE_AES !=
2863 pWextState->roamProfile.EncryptionType.encryptionType[0])
2864 )
2865 {
2866 /* if default key index is not same as previous one,
2867 * then update the default key index */
2868
2869 tCsrRoamSetKey setKey;
2870 v_U32_t roamId= 0xFF;
2871 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
2872
2873 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
2874 __func__, key_index);
2875
2876 Keys->defaultIndex = (u8)key_index;
2877 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2878 setKey.keyId = key_index;
2879 setKey.keyLength = Keys->KeyLength[key_index];
2880
2881 vos_mem_copy(&setKey.Key[0],
2882 &Keys->KeyMaterial[key_index][0],
2883 Keys->KeyLength[key_index]);
2884
2885 setKey.keyDirection = eSIR_TX_ONLY;
2886
2887 vos_mem_copy(setKey.peerMac,
2888 &pHddStaCtx->conn_info.bssId[0],
2889 WNI_CFG_BSSID_LEN);
2890
2891 setKey.encType =
2892 pWextState->roamProfile.EncryptionType.encryptionType[0];
2893
2894 /* issue set key request */
2895 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2896 pAdapter->sessionId, &setKey, &roamId );
2897
2898 if ( 0 != status )
2899 {
2900 hddLog(VOS_TRACE_LEVEL_ERROR,
2901 "%s: sme_RoamSetKey failed, returned %d", __func__,
2902 status);
2903 return -EINVAL;
2904 }
2905 }
2906 }
2907
2908 /* In SoftAp mode setting key direction for default mode */
2909 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
2910 {
2911 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
2912 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
2913 (eCSR_ENCRYPT_TYPE_AES !=
2914 pWextState->roamProfile.EncryptionType.encryptionType[0])
2915 )
2916 {
2917 /* Saving key direction for default key index to TX default */
2918 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2919 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
2920 }
2921 }
2922
2923 return status;
2924}
2925
2926/**
2927 * FUNCTION: wlan_hdd_cfg80211_set_channel
2928 * This function is used to set the channel number
2929 */
2930int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
2931 struct ieee80211_channel *chan,
2932 enum nl80211_channel_type channel_type
2933 )
2934{
2935 v_U32_t num_ch = 0;
2936 u32 channel = 0;
2937 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2938 int freq = chan->center_freq; /* freq is in MHZ */
2939
2940 ENTER();
2941
2942 hddLog(VOS_TRACE_LEVEL_INFO,
2943 "%s: device_mode = %d freq = %d \n",__func__,
2944 pAdapter->device_mode, chan->center_freq);
2945
2946 /*
2947 * Do freq to chan conversion
2948 * TODO: for 11a
2949 */
2950
2951 channel = ieee80211_frequency_to_channel(freq);
2952
2953 /* Check freq range */
2954 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
2955 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
2956 {
2957 hddLog(VOS_TRACE_LEVEL_ERROR,
2958 "%s: Channel [%d] is outside valid range from %d to %d\n",
2959 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
2960 WNI_CFG_CURRENT_CHANNEL_STAMAX);
2961 return -EINVAL;
2962 }
2963
2964 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
2965
2966 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode)
2967#ifdef WLAN_FEATURE_P2P
2968 && (WLAN_HDD_P2P_GO != pAdapter->device_mode)
2969#endif
2970 )
2971 {
2972 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
2973 {
2974 hddLog(VOS_TRACE_LEVEL_ERROR,
2975 "%s: Invalid Channel [%d] \n", __func__, channel);
2976 return -EINVAL;
2977 }
2978 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2979 "%s: set channel to [%d] for device mode =%d",
2980 __func__, channel,pAdapter->device_mode);
2981 }
2982 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2983#ifdef WLAN_FEATURE_P2P
2984 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2985#endif
2986 )
2987 {
2988 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2989 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
2990 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2991
2992 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
2993 {
2994 /* Link is up then return cant set channel*/
2995 hddLog( VOS_TRACE_LEVEL_ERROR,
2996 "%s: IBSS Associated, can't set the channel\n", __func__);
2997 return -EINVAL;
2998 }
2999
3000 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
3001 pHddStaCtx->conn_info.operationChannel = channel;
3002 pRoamProfile->ChannelInfo.ChannelList =
3003 &pHddStaCtx->conn_info.operationChannel;
3004 }
3005 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3006#ifdef WLAN_FEATURE_P2P
3007 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
3008#endif
3009 )
3010 {
3011 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
3012
3013 if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3014 {
3015 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3016
3017 /* If auto channel selection is configured as enable/ 1 then ignore
3018 channel set by supplicant
3019 */
3020 if ( cfg_param->apAutoChannelSelection )
3021 {
3022 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = AUTO_CHANNEL_SELECT;
3023
3024 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3025 "%s: set channel to auto channel (0) for device mode =%d",
3026 __func__, pAdapter->device_mode);
3027 }
3028 }
3029 }
3030 else
3031 {
3032 hddLog(VOS_TRACE_LEVEL_FATAL,
3033 "%s: Invalid device mode failed to set valid channel", __func__);
3034 return -EINVAL;
3035 }
3036 EXIT();
3037 return 0;
3038}
3039
3040
3041
3042/*
3043 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3044 * This function is used to inform the BSS details to nl80211 interface.
3045 */
3046static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3047 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3048{
3049 struct net_device *dev = pAdapter->dev;
3050 struct wireless_dev *wdev = dev->ieee80211_ptr;
3051 struct wiphy *wiphy = wdev->wiphy;
3052 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3053 int chan_no;
3054 int ie_length;
3055 const char *ie;
3056 unsigned int freq;
3057 struct ieee80211_channel *chan;
3058 int rssi = 0;
3059 struct cfg80211_bss *bss = NULL;
3060
3061 ENTER();
3062
3063 if( NULL == pBssDesc )
3064 {
3065 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3066 return bss;
3067 }
3068
3069 chan_no = pBssDesc->channelId;
3070 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3071 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3072
3073 if( NULL == ie )
3074 {
3075 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3076 return bss;
3077 }
3078
3079#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3080 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3081 {
3082 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3083 }
3084 else
3085 {
3086 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3087 }
3088#else
3089 freq = ieee80211_channel_to_frequency(chan_no);
3090#endif
3091
3092 chan = __ieee80211_get_channel(wiphy, freq);
3093
3094 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3095 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3096 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3097 if (bss == NULL)
3098 {
3099 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3100
3101 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3102 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3103 pBssDesc->capabilityInfo,
3104 pBssDesc->beaconInterval, ie, ie_length,
3105 rssi, GFP_KERNEL ));
3106}
3107 else
3108 {
3109 return bss;
3110 }
3111}
3112
3113
3114
3115/*
3116 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3117 * This function is used to inform the BSS details to nl80211 interface.
3118 */
3119struct cfg80211_bss*
3120wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3121 tSirBssDescription *bss_desc
3122 )
3123{
3124 /*
3125 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3126 already exists in bss data base of cfg80211 for that particular BSS ID.
3127 Using cfg80211_inform_bss_frame to update the bss entry instead of
3128 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3129 now there is no possibility to get the mgmt(probe response) frame from PE,
3130 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3131 cfg80211_inform_bss_frame.
3132 */
3133 struct net_device *dev = pAdapter->dev;
3134 struct wireless_dev *wdev = dev->ieee80211_ptr;
3135 struct wiphy *wiphy = wdev->wiphy;
3136 int chan_no = bss_desc->channelId;
3137 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
3138 const char *ie =
3139 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3140 unsigned int freq;
3141 struct ieee80211_channel *chan;
3142 struct ieee80211_mgmt *mgmt =
3143 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3144 struct cfg80211_bss *bss_status = NULL;
3145 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3146 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003147#ifdef WLAN_OPEN_SOURCE
3148 struct timespec ts;
3149#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003150
3151 ENTER();
3152
3153 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003154
3155#ifdef WLAN_OPEN_SOURCE
3156 /* Android does not want the timestamp from the frame.
3157 Instead it wants a monotonic increasing value */
3158 get_monotonic_boottime(&ts);
3159 mgmt->u.probe_resp.timestamp =
3160 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3161#else
3162 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003163 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3164 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003165
3166#endif
3167
Jeff Johnson295189b2012-06-20 16:38:30 -07003168 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3169 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
3170 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3171
3172 mgmt->frame_control |=
3173 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3174
3175#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3176 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3177 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3178 {
3179 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3180 }
3181 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3182 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3183
3184 {
3185 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3186 }
3187 else
3188 {
3189 kfree(mgmt);
3190 return NULL;
3191 }
3192#else
3193 freq = ieee80211_channel_to_frequency(chan_no);
3194#endif
3195 chan = __ieee80211_get_channel(wiphy, freq);
3196
3197 /*To keep the rssi icon of the connected AP in the scan window
3198 *and the rssi icon of the wireless networks in sync
3199 * */
3200 if (( eConnectionState_Associated ==
3201 pAdapter->sessionCtx.station.conn_info.connState ) &&
3202 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3203 pAdapter->sessionCtx.station.conn_info.bssId,
3204 WNI_CFG_BSSID_LEN)))
3205 {
3206 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3207 rssi = (pAdapter->rssi * 100);
3208 }
3209 else
3210 {
3211 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3212 }
3213
3214 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3215 frame_len, rssi, GFP_KERNEL);
3216 kfree(mgmt);
3217 return bss_status;
3218}
3219
3220/*
3221 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3222 * This function is used to update the BSS data base of CFG8011
3223 */
3224struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3225 tCsrRoamInfo *pRoamInfo
3226 )
3227{
3228 tCsrRoamConnectedProfile roamProfile;
3229 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3230 struct cfg80211_bss *bss = NULL;
3231
3232 ENTER();
3233
3234 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
3235 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
3236
3237 if (NULL != roamProfile.pBssDesc)
3238 {
3239 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
3240 &roamProfile);
3241
3242 if (NULL == bss)
3243 {
3244 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
3245 __func__);
3246 }
3247
3248 sme_RoamFreeConnectProfile(hHal, &roamProfile);
3249 }
3250 else
3251 {
3252 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
3253 __func__);
3254 }
3255 return bss;
3256}
3257
3258/*
3259 * FUNCTION: wlan_hdd_cfg80211_update_bss
3260 */
3261static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
3262 hdd_adapter_t *pAdapter
3263 )
3264{
3265 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3266 tCsrScanResultInfo *pScanResult;
3267 eHalStatus status = 0;
3268 tScanResultHandle pResult;
3269 struct cfg80211_bss *bss_status = NULL;
3270
3271 ENTER();
3272
3273 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3274 {
3275 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3276 return -EAGAIN;
3277 }
3278
3279 /*
3280 * start getting scan results and populate cgf80211 BSS database
3281 */
3282 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
3283
3284 /* no scan results */
3285 if (NULL == pResult)
3286 {
3287 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
3288 return status;
3289 }
3290
3291 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
3292
3293 while (pScanResult)
3294 {
3295 /*
3296 * cfg80211_inform_bss() is not updating ie field of bss entry, if
3297 * entry already exists in bss data base of cfg80211 for that
3298 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
3299 * bss entry instead of cfg80211_inform_bss, But this call expects
3300 * mgmt packet as input. As of now there is no possibility to get
3301 * the mgmt(probe response) frame from PE, converting bss_desc to
3302 * ieee80211_mgmt(probe response) and passing to c
3303 * fg80211_inform_bss_frame.
3304 * */
3305
3306 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
3307 &pScanResult->BssDescriptor);
3308
3309
3310 if (NULL == bss_status)
3311 {
3312 hddLog(VOS_TRACE_LEVEL_INFO,
3313 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
3314 }
3315 else
3316 {
3317 cfg80211_put_bss(bss_status);
3318 }
3319
3320 pScanResult = sme_ScanResultGetNext(hHal, pResult);
3321 }
3322
3323 sme_ScanResultPurge(hHal, pResult);
3324
3325 return 0;
3326}
3327
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003328void
3329hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
3330{
3331 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
3332 "%X:%X:%X:%X:%X:%X\n",
3333 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
3334 macAddr[5]);
3335} /****** end hddPrintMacAddr() ******/
3336
3337void
3338hddPrintPmkId(tCsrBssid pmkId, tANI_U8 logLevel)
3339{
3340 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
3341 "%X:%X:%X:%X:%X:%X:%X:%X:%X:%X:%X:%X:%X:%X:%X:%X\n",
3342 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
3343 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9],
3344 pmkId[10], pmkId[11], pmkId[12], pmkId[13], pmkId[14],
3345 pmkId[15]);
3346} /****** end hddPrintPmkId() ******/
3347
3348//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
3349//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
3350
3351//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
3352//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
3353
3354#define dump_bssid(bssid) \
3355 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003356 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
3357 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
3358 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003359 }
3360
3361#define dump_pmkid(pMac, pmkid) \
3362 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003363 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
3364 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
3365 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003366 }
3367
3368#ifdef FEATURE_WLAN_LFR
3369/*
3370 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
3371 * This function is used to notify the supplicant of a new PMKSA candidate.
3372 */
3373int wlan_hdd_cfg80211_pmksa_candidate_notify(
3374 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
3375 int index, bool preauth )
3376{
Jeff Johnsone7245742012-09-05 17:12:55 -07003377#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003378 struct net_device *dev = pAdapter->dev;
3379
3380 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07003381 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003382
3383 if( NULL == pRoamInfo )
3384 {
3385 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
3386 return -EINVAL;
3387 }
3388
3389 dump_bssid(pRoamInfo->bssid);
3390 cfg80211_pmksa_candidate_notify(dev, index,
3391 pRoamInfo->bssid, preauth, GFP_KERNEL);
Jeff Johnsone7245742012-09-05 17:12:55 -07003392#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003393 return 0;
3394}
3395#endif //FEATURE_WLAN_LFR
3396
Jeff Johnson295189b2012-06-20 16:38:30 -07003397/*
3398 * FUNCTION: hdd_cfg80211_scan_done_callback
3399 * scanning callback function, called after finishing scan
3400 *
3401 */
3402static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
3403 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
3404{
3405 struct net_device *dev = (struct net_device *) pContext;
3406 //struct wireless_dev *wdev = dev->ieee80211_ptr;
3407 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
3408 hdd_scaninfo_t *pScanInfo = &pAdapter->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07003409 struct cfg80211_scan_request *req = NULL;
3410 int ret = 0;
3411
3412 ENTER();
3413
3414 hddLog(VOS_TRACE_LEVEL_INFO,
3415 "%s called with halHandle = %p, pContext = %p,"
3416 "scanID = %d, returned status = %d\n",
3417 __func__, halHandle, pContext, (int) scanId, (int) status);
3418
3419 //Block on scan req completion variable. Can't wait forever though.
3420 ret = wait_for_completion_interruptible_timeout(
3421 &pScanInfo->scan_req_completion_event,
3422 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
3423 if (!ret)
3424 {
3425 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003426 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003427 }
3428
3429 if(pScanInfo->mScanPending != VOS_TRUE)
3430 {
3431 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003432 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003433 }
3434
3435 /* Check the scanId */
3436 if (pScanInfo->scanId != scanId)
3437 {
3438 hddLog(VOS_TRACE_LEVEL_INFO,
3439 "%s called with mismatched scanId pScanInfo->scanId = %d "
3440 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
3441 (int) scanId);
3442 }
3443
Jeff Johnson295189b2012-06-20 16:38:30 -07003444 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
3445 pAdapter);
3446
3447 if (0 > ret)
3448 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
3449
3450
3451 /* If any client wait scan result through WEXT
3452 * send scan done event to client */
3453 if (pAdapter->scan_info.waitScanResult)
3454 {
3455 /* The other scan request waiting for current scan finish
3456 * Send event to notify current scan finished */
3457 if(WEXT_SCAN_PENDING_DELAY == pAdapter->scan_info.scan_pending_option)
3458 {
3459 vos_event_set(&pAdapter->scan_info.scan_finished_event);
3460 }
3461 /* Send notify to WEXT client */
3462 else if(WEXT_SCAN_PENDING_PIGGYBACK == pAdapter->scan_info.scan_pending_option)
3463 {
3464 struct net_device *dev = pAdapter->dev;
3465 union iwreq_data wrqu;
3466 int we_event;
3467 char *msg;
3468
3469 memset(&wrqu, '\0', sizeof(wrqu));
3470 we_event = SIOCGIWSCAN;
3471 msg = NULL;
3472 wireless_send_event(dev, we_event, &wrqu, msg);
3473 }
3474 }
3475 pAdapter->scan_info.waitScanResult = FALSE;
3476
3477 /* Get the Scan Req */
3478 req = pAdapter->request;
3479
3480 if (!req)
3481 {
3482 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07003483 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003484 }
3485
3486 /*
3487 * setting up 0, just in case.
3488 */
3489 req->n_ssids = 0;
3490 req->n_channels = 0;
3491 req->ie = 0;
3492
3493 /*
3494 * cfg80211_scan_done informing NL80211 about completion
3495 * of scanning
3496 */
3497 cfg80211_scan_done(req, false);
3498 complete(&pAdapter->abortscan_event_var);
3499 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003500 /* Scan is no longer pending */
3501 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003502
3503#ifdef WLAN_FEATURE_P2P
3504 /* Flush out scan result after p2p_serach is done */
Jeff Johnsone7245742012-09-05 17:12:55 -07003505 if(pScanInfo->flushP2pScanResults)
Jeff Johnson295189b2012-06-20 16:38:30 -07003506 {
3507 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -07003508 sme_ScanFlushResult(WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId);
Jeff Johnsone7245742012-09-05 17:12:55 -07003509 pScanInfo->flushP2pScanResults = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003510 }
3511#endif
3512
Jeff Johnsone7245742012-09-05 17:12:55 -07003513allow_suspend:
3514 /* release the wake lock */
3515 if((eConnectionState_NotConnected ==
3516 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
3517 {
3518 hdd_allow_suspend();
3519 }
3520
Jeff Johnson295189b2012-06-20 16:38:30 -07003521 EXIT();
3522 return 0;
3523}
3524
3525/*
3526 * FUNCTION: wlan_hdd_cfg80211_scan
3527 * this scan respond to scan trigger and update cfg80211 scan database
3528 * later, scan dump command can be used to recieve scan results
3529 */
3530int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, struct net_device *dev,
3531 struct cfg80211_scan_request *request)
3532{
3533 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
3534 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3535 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3536 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3537 tCsrScanRequest scanRequest;
3538 tANI_U8 *channelList = NULL, i;
3539 v_U32_t scanId = 0;
3540 int status = 0;
3541 hdd_scaninfo_t *pScanInfo = &pAdapter->scan_info;
Jeff Johnsone7245742012-09-05 17:12:55 -07003542 v_U8_t preventSuspend = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003543#ifdef WLAN_FEATURE_P2P
3544 v_U8_t* pP2pIe = NULL;
3545#endif
3546
3547 ENTER();
3548
3549 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3550 __func__,pAdapter->device_mode);
3551#ifdef WLAN_BTAMP_FEATURE
3552 //Scan not supported when AMP traffic is on.
3553 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
3554 {
3555 hddLog(VOS_TRACE_LEVEL_ERROR,
3556 "%s: No scanning when AMP is on", __func__);
3557 return -EOPNOTSUPP;
3558 }
3559#endif
3560 //Scan on any other interface is not supported.
3561 if( pAdapter->device_mode == WLAN_HDD_SOFTAP )
3562 {
3563 hddLog(VOS_TRACE_LEVEL_ERROR,
3564 "%s: Not scanning on device_mode = %d",
3565 __func__, pAdapter->device_mode);
3566 return -EOPNOTSUPP;
3567 }
3568
3569 if (TRUE == pScanInfo->mScanPending)
3570 {
3571 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
3572 return -EBUSY;
3573 }
3574
3575 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3576 {
3577 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3578 "%s:LOGP in Progress. Ignore!!!", __func__);
3579 return -EAGAIN;
3580 }
3581
Jeff Johnson32d95a32012-09-10 13:15:23 -07003582 //Don't Allow Scan and return busy if Remain On
3583 //Channel and action frame is pending
3584 //Otherwise Cancel Remain On Channel and allow Scan
3585 //If no action frame pending
3586 if(0 != wlan_hdd_check_remain_on_channel(pAdapter))
3587 {
3588 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
3589 return -EBUSY;
3590 }
3591
Jeff Johnson295189b2012-06-20 16:38:30 -07003592 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
3593 {
3594 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
3595 "%s: Aquire lock fail", __func__);
3596 return -EAGAIN;
3597 }
3598 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
3599 {
3600 hddLog(VOS_TRACE_LEVEL_WARN,
3601 "%s: MAX TM Level Scan not allowed", __func__);
3602 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
3603 return -EBUSY;
3604 }
3605 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
3606
3607 vos_mem_zero( &scanRequest, sizeof(scanRequest));
3608
3609 if (NULL != request)
3610 {
3611 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
3612 (int)request->n_ssids);
3613
3614 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
3615 * Becasue of this, driver is assuming that this is not wildcard scan and so
3616 * is not aging out the scan results.
3617 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07003618 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07003619 {
3620 request->n_ssids = 0;
3621 }
3622
3623 if (0 < request->n_ssids)
3624 {
3625 tCsrSSIDInfo *SsidInfo;
3626 int j;
3627 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
3628 /* Allocate num_ssid tCsrSSIDInfo structure */
3629 SsidInfo = scanRequest.SSIDs.SSIDList =
3630 ( tCsrSSIDInfo *)vos_mem_malloc(
3631 request->n_ssids*sizeof(tCsrSSIDInfo));
3632
3633 if(NULL == scanRequest.SSIDs.SSIDList)
3634 {
3635 hddLog(VOS_TRACE_LEVEL_ERROR,
3636 "memory alloc failed SSIDInfo buffer");
3637 return -ENOMEM;
3638 }
3639
3640 /* copy all the ssid's and their length */
3641 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
3642 {
3643 /* get the ssid length */
3644 SsidInfo->SSID.length = request->ssids[j].ssid_len;
3645 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
3646 SsidInfo->SSID.length);
3647 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
3648 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
3649 j, SsidInfo->SSID.ssId);
3650 }
3651 /* set the scan type to active */
3652 scanRequest.scanType = eSIR_ACTIVE_SCAN;
3653 }
3654 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
3655 {
3656 /* set the scan type to active */
3657 scanRequest.scanType = eSIR_ACTIVE_SCAN;
3658 }
3659 else
3660 {
3661 /*Set the scan type to default type, in this case it is ACTIVE*/
3662 scanRequest.scanType = pScanInfo->scan_mode;
3663 }
3664 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
3665 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
3666 }
3667 else
3668 {
3669 /* set the scan type to active */
3670 scanRequest.scanType = eSIR_ACTIVE_SCAN;
3671 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
3672
3673 /* set min and max channel time to zero */
3674 scanRequest.minChnTime = 0;
3675 scanRequest.maxChnTime = 0;
3676 }
3677
3678 /* set BSSType to default type */
3679 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
3680
3681 /*TODO: scan the requested channels only*/
3682
3683 /*Right now scanning all the channels */
3684 if( request )
3685 {
3686 if( request->n_channels )
3687 {
3688 channelList = vos_mem_malloc( request->n_channels );
3689 if( NULL == channelList )
3690 {
3691 status = -ENOMEM;
3692 goto free_mem;
3693 }
3694
3695 for( i = 0 ; i < request->n_channels ; i++ )
3696 channelList[i] = request->channels[i]->hw_value;
3697 }
3698
3699 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
3700 scanRequest.ChannelInfo.ChannelList = channelList;
3701
3702 /* set requestType to full scan */
3703 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
3704
3705 if( request->ie_len )
3706 {
3707 /* save this for future association (join requires this) */
3708 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
3709 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
3710 pScanInfo->scanAddIE.length = request->ie_len;
3711
3712 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07003713 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
3714 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07003715 )
3716 {
3717 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
3718 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
3719 }
3720
3721 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
3722 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
3723
3724#ifdef WLAN_FEATURE_P2P
3725 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
3726 request->ie_len);
3727 if (pP2pIe != NULL)
3728 {
Jeff Johnsone7245742012-09-05 17:12:55 -07003729 /* no_cck will be set during p2p find to disable 11b rates */
3730 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07003731 {
3732 tANI_U8 sessionId = pAdapter->sessionId;
3733 hddLog(VOS_TRACE_LEVEL_INFO,
3734 "%s: This is a P2P Search", __func__);
3735 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07003736
3737 /* Flush the scan results only for P2P search.
3738 P2P search happens on 3 social channels (1, 6, 11) */
3739 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
3740 {
3741 pScanInfo->flushP2pScanResults = 1;
3742 sme_ScanFlushResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
3743 sessionId );
3744 }
3745
3746 /*
3747 Skip Dfs Channel in case of P2P Search
3748 if it is set in ini file
3749 */
3750 if(cfg_param->skipDfsChnlInP2pSearch)
3751 {
3752 scanRequest.skipDfsChnlInP2pSearch = 1;
3753 }
3754 else
3755 {
3756 scanRequest.skipDfsChnlInP2pSearch = 0;
3757 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003758
3759 /* set requestType to P2P Discovery */
3760 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnson295189b2012-06-20 16:38:30 -07003761 }
3762 }
3763#endif
3764 }
3765 }
3766
3767 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
3768
Jeff Johnsone7245742012-09-05 17:12:55 -07003769 /*If the station is not connected and recieved a scan request, acquire the
3770 * wake lock to not request the suspend from Android*/
3771 if((eConnectionState_NotConnected ==
3772 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07003773 {
Jeff Johnsone7245742012-09-05 17:12:55 -07003774 preventSuspend = 1;
3775 hdd_prevent_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07003776 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003777
3778 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07003779 pAdapter->sessionId, &scanRequest, &scanId,
3780 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07003781
Jeff Johnson295189b2012-06-20 16:38:30 -07003782 if (eHAL_STATUS_SUCCESS != status)
3783 {
3784 hddLog(VOS_TRACE_LEVEL_ERROR,
3785 "%s: sme_ScanRequest returned error %d", __func__, status);
3786 complete(&pScanInfo->scan_req_completion_event);
3787 status = -EIO;
Jeff Johnsone7245742012-09-05 17:12:55 -07003788 if(preventSuspend)
3789 {
3790 hdd_allow_suspend();
3791 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003792 goto free_mem;
3793 }
3794
3795 pScanInfo->mScanPending = TRUE;
3796 pAdapter->request = request;
3797 pScanInfo->scanId = scanId;
3798
3799 complete(&pScanInfo->scan_req_completion_event);
3800
3801free_mem:
3802 if( scanRequest.SSIDs.SSIDList )
3803 {
3804 vos_mem_free(scanRequest.SSIDs.SSIDList);
3805 }
3806
3807 if( channelList )
3808 vos_mem_free( channelList );
3809
3810 EXIT();
3811
3812 return status;
3813}
3814
3815/*
3816 * FUNCTION: wlan_hdd_cfg80211_connect_start
3817 * This function is used to start the association process
3818 */
3819int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07003820 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07003821{
3822 int status = 0;
3823 hdd_wext_state_t *pWextState;
3824 v_U32_t roamId;
3825 tCsrRoamProfile *pRoamProfile;
3826 eMib_dot11DesiredBssType connectedBssType;
3827 eCsrAuthType RSNAuthType;
3828
3829 ENTER();
3830
3831 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3832
3833 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
3834 {
3835 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
3836 return -EINVAL;
3837 }
3838
3839 pRoamProfile = &pWextState->roamProfile;
3840
3841 if (pRoamProfile)
3842 {
Jeff Johnsone7245742012-09-05 17:12:55 -07003843 int ret = 0;
3844 hdd_station_ctx_t *pHddStaCtx;
3845 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3846 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
3847
3848 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
3849 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
3850 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07003851 {
3852 /* Issue disconnect to CSR */
3853 INIT_COMPLETION(pAdapter->disconnect_comp_var);
3854 if( eHAL_STATUS_SUCCESS ==
3855 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
3856 pAdapter->sessionId,
3857 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
3858 {
Jeff Johnsone7245742012-09-05 17:12:55 -07003859 ret = wait_for_completion_interruptible_timeout(
3860 &pAdapter->disconnect_comp_var,
3861 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3862 if (0 == ret)
3863 {
3864 VOS_ASSERT(0);
3865 }
3866 }
3867 }
3868 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
3869 {
3870 ret = wait_for_completion_interruptible_timeout(
3871 &pAdapter->disconnect_comp_var,
3872 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3873 if (0 == ret)
3874 {
3875 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07003876 }
3877 }
3878
3879 if (HDD_WMM_USER_MODE_NO_QOS ==
3880 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
3881 {
3882 /*QoS not enabled in cfg file*/
3883 pRoamProfile->uapsd_mask = 0;
3884 }
3885 else
3886 {
3887 /*QoS enabled, update uapsd mask from cfg file*/
3888 pRoamProfile->uapsd_mask =
3889 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
3890 }
3891
3892 pRoamProfile->SSIDs.numOfSSIDs = 1;
3893 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
3894 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
3895 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
3896 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
3897 ssid, ssid_len);
3898
3899 if (bssid)
3900 {
3901 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
3902 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
3903 WNI_CFG_BSSID_LEN);
3904 /* Save BSSID in seperate variable as well, as RoamProfile
3905 BSSID is getting zeroed out in the association process. And in
3906 case of join failure we should send valid BSSID to supplicant
3907 */
3908 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
3909 WNI_CFG_BSSID_LEN);
3910 }
3911
3912 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
3913 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
3914 {
3915 /*set gen ie*/
3916 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
3917 /*set auth*/
3918 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
3919 }
3920 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
3921 eCSR_AUTH_TYPE_OPEN_SYSTEM)
3922 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
3923 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
3924 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
3925 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
3926 )
3927 {
3928 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
3929 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
3930 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
3931 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
3932 eCSR_AUTH_TYPE_AUTOSWITCH;
3933 pWextState->roamProfile.AuthType.authType[0] =
3934 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
3935 }
3936#ifdef FEATURE_WLAN_WAPI
3937 if (pAdapter->wapi_info.nWapiMode)
3938 {
3939 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __FUNCTION__);
3940 switch (pAdapter->wapi_info.wapiAuthMode)
3941 {
3942 case WAPI_AUTH_MODE_PSK:
3943 {
3944 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __FUNCTION__,
3945 pAdapter->wapi_info.wapiAuthMode);
3946 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
3947 break;
3948 }
3949 case WAPI_AUTH_MODE_CERT:
3950 {
3951 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __FUNCTION__,
3952 pAdapter->wapi_info.wapiAuthMode);
3953 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
3954 break;
3955 }
3956 } // End of switch
3957 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
3958 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
3959 {
3960 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __FUNCTION__);
3961 pRoamProfile->AuthType.numEntries = 1;
3962 pRoamProfile->EncryptionType.numEntries = 1;
3963 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
3964 pRoamProfile->mcEncryptionType.numEntries = 1;
3965 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
3966 }
3967 }
3968#endif /* FEATURE_WLAN_WAPI */
3969 pRoamProfile->csrPersona = pAdapter->device_mode;
3970
Jeff Johnson32d95a32012-09-10 13:15:23 -07003971 if( operatingChannel )
3972 {
3973 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
3974 pRoamProfile->ChannelInfo.numOfChannels = 1;
3975 }
3976
Jeff Johnson295189b2012-06-20 16:38:30 -07003977 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
3978 pAdapter->sessionId, pRoamProfile, &roamId);
3979
Jeff Johnson32d95a32012-09-10 13:15:23 -07003980 pRoamProfile->ChannelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003981 pRoamProfile->ChannelInfo.numOfChannels = 0;
3982 }
3983 else
3984 {
3985 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
3986 return -EINVAL;
3987 }
3988 EXIT();
3989 return status;
3990}
3991
3992/*
3993 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
3994 * This function is used to set the authentication type (OPEN/SHARED).
3995 *
3996 */
3997static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
3998 enum nl80211_auth_type auth_type)
3999{
4000 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4001 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4002
4003 ENTER();
4004
4005 /*set authentication type*/
4006 switch (auth_type)
4007 {
4008 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4009 case NL80211_AUTHTYPE_AUTOMATIC:
4010 hddLog(VOS_TRACE_LEVEL_INFO,
4011 "%s: set authentication type to OPEN", __func__);
4012 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4013 break;
4014
4015 case NL80211_AUTHTYPE_SHARED_KEY:
4016 hddLog(VOS_TRACE_LEVEL_INFO,
4017 "%s: set authentication type to SHARED", __func__);
4018 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4019 break;
4020#ifdef FEATURE_WLAN_CCX
4021 case NL80211_AUTHTYPE_NETWORK_EAP:
4022 hddLog(VOS_TRACE_LEVEL_INFO,
4023 "%s: set authentication type to CCKM WPA", __func__);
4024 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4025 break;
4026#endif
4027
4028
4029 default:
4030 hddLog(VOS_TRACE_LEVEL_ERROR,
4031 "%s: Unsupported authentication type %d", __func__,
4032 auth_type);
4033 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4034 return -EINVAL;
4035 }
4036
4037 pWextState->roamProfile.AuthType.authType[0] =
4038 pHddStaCtx->conn_info.authType;
4039 return 0;
4040}
4041
4042/*
4043 * FUNCTION: wlan_hdd_set_akm_suite
4044 * This function is used to set the key mgmt type(PSK/8021x).
4045 *
4046 */
4047static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
4048 u32 key_mgmt
4049 )
4050{
4051 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4052 ENTER();
4053
4054 /*set key mgmt type*/
4055 switch(key_mgmt)
4056 {
4057 case WLAN_AKM_SUITE_PSK:
4058 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
4059 __func__);
4060 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
4061 break;
4062
4063 case WLAN_AKM_SUITE_8021X:
4064 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
4065 __func__);
4066 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
4067 break;
4068#ifdef FEATURE_WLAN_CCX
4069#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
4070#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
4071 case WLAN_AKM_SUITE_CCKM:
4072 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
4073 __func__);
4074 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
4075 break;
4076#endif
4077
4078 default:
4079 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
4080 __func__, key_mgmt);
4081 return -EINVAL;
4082
4083 }
4084 return 0;
4085}
4086
4087/*
4088 * FUNCTION: wlan_hdd_cfg80211_set_cipher
4089 * This function is used to set the encryption type
4090 * (NONE/WEP40/WEP104/TKIP/CCMP).
4091 */
4092static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
4093 u32 cipher,
4094 bool ucast
4095 )
4096{
4097 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4098 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4099 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4100
4101 ENTER();
4102
4103 if (!cipher)
4104 {
4105 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
4106 __func__, cipher);
4107 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4108 }
4109 else
4110 {
4111
4112 /*set encryption method*/
4113 switch (cipher)
4114 {
4115 case IW_AUTH_CIPHER_NONE:
4116 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4117 break;
4118
4119 case WLAN_CIPHER_SUITE_WEP40:
4120 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4121 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4122 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
4123 else
4124 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4125 break;
4126
4127 case WLAN_CIPHER_SUITE_WEP104:
4128 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4129 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4130 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
4131 else
4132 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
4133 break;
4134
4135 case WLAN_CIPHER_SUITE_TKIP:
4136 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
4137 break;
4138
4139 case WLAN_CIPHER_SUITE_CCMP:
4140 encryptionType = eCSR_ENCRYPT_TYPE_AES;
4141 break;
4142#ifdef FEATURE_WLAN_WAPI
4143 case WLAN_CIPHER_SUITE_SMS4:
4144 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
4145 break;
4146#endif
4147
4148#ifdef FEATURE_WLAN_CCX
4149 case WLAN_CIPHER_SUITE_KRK:
4150 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
4151 break;
4152#endif
4153 default:
4154 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
4155 __func__, cipher);
4156 return -EOPNOTSUPP;
4157 }
4158 }
4159
4160 if (ucast)
4161 {
4162 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
4163 __func__, encryptionType);
4164 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
4165 pWextState->roamProfile.EncryptionType.numEntries = 1;
4166 pWextState->roamProfile.EncryptionType.encryptionType[0] =
4167 encryptionType;
4168 }
4169 else
4170 {
4171 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
4172 __func__, encryptionType);
4173 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
4174 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
4175 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
4176 }
4177
4178 return 0;
4179}
4180
4181
4182/*
4183 * FUNCTION: wlan_hdd_cfg80211_set_ie
4184 * This function is used to parse WPA/RSN IE's.
4185 */
4186int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
4187 u8 *ie,
4188 size_t ie_len
4189 )
4190{
4191 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4192 u8 *genie = ie;
4193 v_U16_t remLen = ie_len;
4194#ifdef FEATURE_WLAN_WAPI
4195 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
4196 u16 *tmp;
4197 v_U16_t akmsuiteCount;
4198 int *akmlist;
4199#endif
4200 ENTER();
4201
4202 /* clear previous assocAddIE */
4203 pWextState->assocAddIE.length = 0;
4204 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
4205
4206 while (remLen >= 2)
4207 {
4208 v_U16_t eLen = 0;
4209 v_U8_t elementId;
4210 elementId = *genie++;
4211 eLen = *genie++;
4212 remLen -= 2;
4213
4214 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
4215 __func__, elementId, eLen);
4216
4217 switch ( elementId )
4218 {
4219 case DOT11F_EID_WPA:
4220 if ((2+4) > eLen) /* should have at least OUI */
4221 {
4222 hddLog(VOS_TRACE_LEVEL_ERROR,
4223 "%s: Invalid WPA IE", __func__);
4224 return -EINVAL;
4225 }
4226 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
4227 {
4228 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4229 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
4230 __func__, eLen + 2);
4231
4232 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4233 {
4234 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE. "
4235 "Need bigger buffer space\n");
4236 VOS_ASSERT(0);
4237 return -ENOMEM;
4238 }
4239 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4240 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4241 pWextState->assocAddIE.length += eLen + 2;
4242
4243 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
4244 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4245 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4246 }
4247 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
4248 {
4249 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
4250 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4251 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
4252 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
4253 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
4254 }
4255#ifdef WLAN_FEATURE_P2P
4256 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
4257 P2P_OUI_TYPE_SIZE))
4258 /*Consider P2P IE, only for P2P Client */
4259 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4260 {
4261 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4262 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
4263 __func__, eLen + 2);
4264
4265 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4266 {
4267 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
4268 "Need bigger buffer space\n");
4269 VOS_ASSERT(0);
4270 return -ENOMEM;
4271 }
4272 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4273 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4274 pWextState->assocAddIE.length += eLen + 2;
4275
4276 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4277 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4278 }
4279#endif
4280#ifdef WLAN_FEATURE_WFD
4281 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
4282 WFD_OUI_TYPE_SIZE))
4283 /*Consider WFD IE, only for P2P Client */
4284 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4285 {
4286 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4287 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
4288 __func__, eLen + 2);
4289
4290 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4291 {
4292 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
4293 "Need bigger buffer space\n");
4294 VOS_ASSERT(0);
4295 return -ENOMEM;
4296 }
4297 // WFD IE is saved to Additional IE ; it should be accumulated to handle
4298 // WPS IE + P2P IE + WFD IE
4299 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4300 pWextState->assocAddIE.length += eLen + 2;
4301
4302 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4303 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4304 }
4305#endif
4306 break;
4307 case DOT11F_EID_RSN:
4308 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
4309 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4310 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
4311 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
4312 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
4313 break;
4314#ifdef FEATURE_WLAN_WAPI
4315 case WLAN_EID_WAPI:
4316 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
4317 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
4318 pAdapter->wapi_info.nWapiMode);
4319 tmp = (u16 *)ie;
4320 tmp = tmp + 2; // Skip element Id and Len, Version
4321 akmsuiteCount = WPA_GET_LE16(tmp);
4322 tmp = tmp + 1;
4323 akmlist = (int *)(tmp);
4324 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
4325 {
4326 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
4327 }
4328 else
4329 {
4330 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
4331 VOS_ASSERT(0);
4332 return -EINVAL;
4333 }
4334
4335 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
4336 {
4337 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
4338 __FUNCTION__);
4339 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
4340 }
4341 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
4342 {
4343 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
4344 __FUNCTION__);
4345 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
4346 }
4347 break;
4348#endif
4349 default:
4350 hddLog (VOS_TRACE_LEVEL_ERROR,
4351 "%s Set UNKNOWN IE %X", __func__, elementId);
4352 return 0;
4353 }
4354 genie += eLen;
4355 remLen -= eLen;
4356 }
4357 EXIT();
4358 return 0;
4359}
4360
4361/*
4362 * FUNCTION: wlan_hdd_cfg80211_set_privacy
4363 * This function is used to initialize the security
4364 * parameters during connect operation.
4365 */
4366int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
4367 struct cfg80211_connect_params *req
4368 )
4369{
4370 int status = 0;
4371 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4372 ENTER();
4373
4374 /*set wpa version*/
4375 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
4376
4377 if (req->crypto.wpa_versions)
4378 {
4379 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
4380 && ( (req->ie_len)
4381 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
4382 // Make sure that it is including a WPA IE.
4383 /* Currently NL is putting WPA version 1 even for open,
4384 * since p2p ie is also put in same buffer.
4385 * */
4386 {
4387 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
4388 }
4389 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
4390 {
4391 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
4392 }
4393 }
4394
4395 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
4396 pWextState->wpaVersion);
4397
4398 /*set authentication type*/
4399 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
4400
4401 if (0 > status)
4402 {
4403 hddLog(VOS_TRACE_LEVEL_ERROR,
4404 "%s: failed to set authentication type ", __func__);
4405 return status;
4406 }
4407
4408 /*set key mgmt type*/
4409 if (req->crypto.n_akm_suites)
4410 {
4411 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
4412 if (0 > status)
4413 {
4414 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
4415 __func__);
4416 return status;
4417 }
4418 }
4419
4420 /*set pairwise cipher type*/
4421 if (req->crypto.n_ciphers_pairwise)
4422 {
4423 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
4424 req->crypto.ciphers_pairwise[0], true);
4425 if (0 > status)
4426 {
4427 hddLog(VOS_TRACE_LEVEL_ERROR,
4428 "%s: failed to set unicast cipher type", __func__);
4429 return status;
4430 }
4431 }
4432 else
4433 {
4434 /*Reset previous cipher suite to none*/
4435 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
4436 if (0 > status)
4437 {
4438 hddLog(VOS_TRACE_LEVEL_ERROR,
4439 "%s: failed to set unicast cipher type", __func__);
4440 return status;
4441 }
4442 }
4443
4444 /*set group cipher type*/
4445 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
4446 false);
4447
4448 if (0 > status)
4449 {
4450 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
4451 __func__);
4452 return status;
4453 }
4454
4455 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
4456 if (req->ie_len)
4457 {
4458 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
4459 if ( 0 > status)
4460 {
4461 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
4462 __func__);
4463 return status;
4464 }
4465 }
4466
4467 /*incase of WEP set default key information*/
4468 if (req->key && req->key_len)
4469 {
4470 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
4471 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
4472 )
4473 {
4474 if ( IW_AUTH_KEY_MGMT_802_1X
4475 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
4476 {
4477 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
4478 __func__);
4479 return -EOPNOTSUPP;
4480 }
4481 else
4482 {
4483 u8 key_len = req->key_len;
4484 u8 key_idx = req->key_idx;
4485
4486 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
4487 && (CSR_MAX_NUM_KEY > key_idx)
4488 )
4489 {
4490 hddLog(VOS_TRACE_LEVEL_INFO,
4491 "%s: setting default wep key, key_idx = %hu key_len %hu",
4492 __func__, key_idx, key_len);
4493 vos_mem_copy(
4494 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
4495 req->key, key_len);
4496 pWextState->roamProfile.Keys.KeyLength[key_idx] =
4497 (u8)key_len;
4498 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
4499 }
4500 }
4501 }
4502 }
4503
4504 return status;
4505}
4506
4507/*
4508 * FUNCTION: wlan_hdd_cfg80211_set_privacy
4509 * This function is used to initialize the security
4510 * parameters during connect operation.
4511 */
4512static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
4513 struct net_device *ndev,
4514 struct cfg80211_connect_params *req
4515 )
4516{
4517 int status = 0;
4518 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
4519 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
4520 hdd_context_t *pHddCtx = NULL;
4521
4522 ENTER();
4523
4524 hddLog(VOS_TRACE_LEVEL_INFO,
4525 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
4526
4527 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
4528 {
4529 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4530 "%s:LOGP in Progress. Ignore!!!", __func__);
4531 return -EAGAIN;
4532 }
4533
4534#ifdef WLAN_BTAMP_FEATURE
4535 //Infra connect not supported when AMP traffic is on.
4536 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
4537 {
4538 hddLog(VOS_TRACE_LEVEL_ERROR,
4539 "%s: No connection when AMP is on", __func__);
4540 return -1;
4541 }
4542#endif
4543 /*initialise security parameters*/
4544 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
4545
4546 if ( 0 > status)
4547 {
4548 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
4549 __func__);
4550 return status;
4551 }
4552
4553 //If Device Mode is Station Concurrent Sessions Exit BMps
4554 //P2P Mode will be taken care in Open/close adaptor
4555 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
4556 (vos_concurrent_sessions_running()))
4557 {
4558 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
4559
4560 if (NULL != pVosContext)
4561 {
4562 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
4563 if(NULL != pHddCtx)
4564 {
4565 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
4566 }
4567 }
4568 }
4569
4570 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004571 req->ssid_len, req->bssid,
4572 req->channel->hw_value);
Jeff Johnson295189b2012-06-20 16:38:30 -07004573
4574 if (0 > status)
4575 {
4576 //ReEnable BMPS if disabled
4577 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
4578 (NULL != pHddCtx))
4579 {
4580 //ReEnable Bmps and Imps back
4581 hdd_enable_bmps_imps(pHddCtx);
4582 }
4583
4584 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
4585 return status;
4586 }
4587 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
4588 EXIT();
4589 return status;
4590}
4591
4592
4593/*
4594 * FUNCTION: wlan_hdd_cfg80211_disconnect
4595 * This function is used to issue a disconnect request to SME
4596 */
4597static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
4598 struct net_device *dev,
4599 u16 reason
4600 )
4601{
4602 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4603 tCsrRoamProfile *pRoamProfile =
4604 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
4605 int status = 0;
4606 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4607
4608 ENTER();
4609
4610 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4611 __func__,pAdapter->device_mode);
4612
4613 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
4614 __func__, reason);
4615
4616 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4617 {
4618 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4619 "%s:LOGP in Progress. Ignore!!!",__func__);
4620 return -EAGAIN;
4621 }
4622 if (NULL != pRoamProfile)
4623 {
4624 /*issue disconnect request to SME, if station is in connected state*/
4625 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
4626 {
4627 eCsrRoamDisconnectReason reasonCode =
4628 eCSR_DISCONNECT_REASON_UNSPECIFIED;
4629 switch(reason)
4630 {
4631 case WLAN_REASON_MIC_FAILURE:
4632 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
4633 break;
4634
4635 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
4636 case WLAN_REASON_DISASSOC_AP_BUSY:
4637 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
4638 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
4639 break;
4640
4641 case WLAN_REASON_PREV_AUTH_NOT_VALID:
4642 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
4643 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
4644 break;
4645
4646 case WLAN_REASON_DEAUTH_LEAVING:
4647 default:
4648 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
4649 break;
4650 }
4651 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4652 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
4653 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4654
4655 /*issue disconnect*/
4656 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4657 pAdapter->sessionId, reasonCode);
4658
4659 if ( 0 != status)
4660 {
4661 hddLog(VOS_TRACE_LEVEL_ERROR,
4662 "%s csrRoamDisconnect failure, returned %d \n",
4663 __func__, (int)status );
4664 return -EINVAL;
4665 }
4666
4667 wait_for_completion_interruptible_timeout(
4668 &pAdapter->disconnect_comp_var,
4669 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4670
4671
4672 /*stop tx queues*/
4673 netif_tx_disable(dev);
4674 netif_carrier_off(dev);
4675 }
4676 }
4677 else
4678 {
4679 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
4680 }
4681
4682 return status;
4683}
4684
4685/*
4686 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
4687 * This function is used to initialize the security
4688 * settings in IBSS mode.
4689 */
4690static int wlan_hdd_cfg80211_set_privacy_ibss(
4691 hdd_adapter_t *pAdapter,
4692 struct cfg80211_ibss_params *params
4693 )
4694{
4695 int status = 0;
4696 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4697 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4698 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4699
4700 ENTER();
4701
4702 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
4703
4704 if (params->ie_len && ( NULL != params->ie) )
4705 {
4706 if (WLAN_EID_RSN == params->ie[0])
4707 {
4708 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
4709 encryptionType = eCSR_ENCRYPT_TYPE_AES;
4710 }
4711 else
4712 {
4713 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
4714 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
4715 }
4716 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
4717
4718 if (0 > status)
4719 {
4720 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
4721 __func__);
4722 return status;
4723 }
4724 }
4725
4726 pWextState->roamProfile.AuthType.authType[0] =
4727 pHddStaCtx->conn_info.authType =
4728 eCSR_AUTH_TYPE_OPEN_SYSTEM;
4729
4730 if (params->privacy)
4731 {
4732 /* Security enabled IBSS, At this time there is no information available
4733 * about the security paramters, so initialise the encryption type to
4734 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
4735 * The correct security parameters will be updated later in
4736 * wlan_hdd_cfg80211_add_key */
4737 /* Hal expects encryption type to be set inorder
4738 *enable privacy bit in beacons */
4739
4740 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4741 }
4742
4743 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
4744 pWextState->roamProfile.EncryptionType.numEntries = 1;
4745 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
4746
4747 return status;
4748}
4749
4750/*
4751 * FUNCTION: wlan_hdd_cfg80211_join_ibss
4752 * This function is used to create/join an IBSS
4753 */
4754static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
4755 struct net_device *dev,
4756 struct cfg80211_ibss_params *params
4757 )
4758{
4759 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4760 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4761 tCsrRoamProfile *pRoamProfile;
4762 int status;
4763 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4764
4765 ENTER();
4766
4767 hddLog(VOS_TRACE_LEVEL_INFO,
4768 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
4769
4770 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
4771 {
4772 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4773 "%s:LOGP in Progress. Ignore!!!", __func__);
4774 return -EAGAIN;
4775 }
4776
4777 if (NULL == pWextState)
4778 {
4779 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
4780 __func__);
4781 return -EIO;
4782 }
4783
4784 pRoamProfile = &pWextState->roamProfile;
4785
4786 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
4787 {
4788 hddLog (VOS_TRACE_LEVEL_ERROR,
4789 "%s Interface type is not set to IBSS \n", __func__);
4790 return -EINVAL;
4791 }
4792
4793 /* Set Channel */
4794 if (NULL != params->channel)
4795 {
4796 u8 channelNum;
4797 if (IEEE80211_BAND_5GHZ == params->channel->band)
4798 {
4799 hddLog(VOS_TRACE_LEVEL_ERROR,
4800 "%s: IBSS join is called with unsupported band %d",
4801 __func__, params->channel->band);
4802 return -EOPNOTSUPP;
4803 }
4804
4805 /* Get channel number */
4806 channelNum =
4807 ieee80211_frequency_to_channel(params->channel->center_freq);
4808
4809 /*TODO: use macro*/
4810 if (14 >= channelNum)
4811 {
4812 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
4813 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
4814 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4815 int indx;
4816
4817 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
4818 validChan, &numChans))
4819 {
4820 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
4821 __func__);
4822 return -EOPNOTSUPP;
4823 }
4824
4825 for (indx = 0; indx < numChans; indx++)
4826 {
4827 if (channelNum == validChan[indx])
4828 {
4829 break;
4830 }
4831 }
4832 if (indx >= numChans)
4833 {
4834 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
4835 __func__, channelNum);
4836 return -EINVAL;
4837 }
4838 /* Set the Operational Channel */
4839 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
4840 channelNum);
4841 pRoamProfile->ChannelInfo.numOfChannels = 1;
4842 pHddStaCtx->conn_info.operationChannel = channelNum;
4843 pRoamProfile->ChannelInfo.ChannelList =
4844 &pHddStaCtx->conn_info.operationChannel;
4845 }
4846 else
4847 {
4848 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
4849 __func__, channelNum);
4850 return -EINVAL;
4851 }
4852 }
4853
4854 /* Initialize security parameters */
4855 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
4856 if (status < 0)
4857 {
4858 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
4859 __func__);
4860 return status;
4861 }
4862
4863 /* Issue connect start */
4864 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004865 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004866
4867 if (0 > status)
4868 {
4869 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
4870 return status;
4871 }
4872
4873 return 0;
4874}
4875
4876/*
4877 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
4878 * This function is used to leave an IBSS
4879 */
4880static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
4881 struct net_device *dev
4882 )
4883{
4884 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4885 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4886 tCsrRoamProfile *pRoamProfile;
4887
4888 ENTER();
4889
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004890 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
4891 {
4892 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4893 "%s:LOGP in Progress. Ignore!!!", __func__);
4894 return -EAGAIN;
4895 }
4896
Jeff Johnson295189b2012-06-20 16:38:30 -07004897 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
4898 if (NULL == pWextState)
4899 {
4900 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
4901 __func__);
4902 return -EIO;
4903 }
4904
4905 pRoamProfile = &pWextState->roamProfile;
4906
4907 /* Issue disconnect only if interface type is set to IBSS */
4908 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
4909 {
4910 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
4911 __func__);
4912 return -EINVAL;
4913 }
4914
4915 /* Issue Disconnect request */
4916 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4917 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
4918 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
4919
4920 return 0;
4921}
4922
4923/*
4924 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
4925 * This function is used to set the phy parameters
4926 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
4927 */
4928static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
4929 u32 changed)
4930{
4931 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
4932 tHalHandle hHal = pHddCtx->hHal;
4933
4934 ENTER();
4935
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004936 if ( pHddCtx->isLogpInProgress )
4937 {
4938 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4939 "%s:LOGP in Progress. Ignore!!!", __func__);
4940 return -EAGAIN;
4941 }
4942
Jeff Johnson295189b2012-06-20 16:38:30 -07004943 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
4944 {
4945 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
4946 WNI_CFG_RTS_THRESHOLD_STAMAX :
4947 wiphy->rts_threshold;
4948
4949 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
4950 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
4951 {
4952 hddLog(VOS_TRACE_LEVEL_ERROR,
4953 "%s: Invalid RTS Threshold value %hu",
4954 __func__, rts_threshold);
4955 return -EINVAL;
4956 }
4957
4958 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
4959 rts_threshold, ccmCfgSetCallback,
4960 eANI_BOOLEAN_TRUE))
4961 {
4962 hddLog(VOS_TRACE_LEVEL_ERROR,
4963 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
4964 __func__, rts_threshold);
4965 return -EIO;
4966 }
4967
4968 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
4969 rts_threshold);
4970 }
4971
4972 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
4973 {
4974 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
4975 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
4976 wiphy->frag_threshold;
4977
4978 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
4979 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
4980 {
4981 hddLog(VOS_TRACE_LEVEL_ERROR,
4982 "%s: Invalid frag_threshold value %hu", __func__,
4983 frag_threshold);
4984 return -EINVAL;
4985 }
4986
4987 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
4988 frag_threshold, ccmCfgSetCallback,
4989 eANI_BOOLEAN_TRUE))
4990 {
4991 hddLog(VOS_TRACE_LEVEL_ERROR,
4992 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
4993 __func__, frag_threshold);
4994 return -EIO;
4995 }
4996
4997 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
4998 frag_threshold);
4999 }
5000
5001 if ((changed & WIPHY_PARAM_RETRY_SHORT)
5002 || (changed & WIPHY_PARAM_RETRY_LONG))
5003 {
5004 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
5005 wiphy->retry_short :
5006 wiphy->retry_long;
5007
5008 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
5009 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
5010 {
5011 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
5012 __func__, retry_value);
5013 return -EINVAL;
5014 }
5015
5016 if (changed & WIPHY_PARAM_RETRY_SHORT)
5017 {
5018 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
5019 retry_value, ccmCfgSetCallback,
5020 eANI_BOOLEAN_TRUE))
5021 {
5022 hddLog(VOS_TRACE_LEVEL_ERROR,
5023 "%s: ccmCfgSetInt failed for long retry count %hu",
5024 __func__, retry_value);
5025 return -EIO;
5026 }
5027 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
5028 __func__, retry_value);
5029 }
5030 else if (changed & WIPHY_PARAM_RETRY_SHORT)
5031 {
5032 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
5033 retry_value, ccmCfgSetCallback,
5034 eANI_BOOLEAN_TRUE))
5035 {
5036 hddLog(VOS_TRACE_LEVEL_ERROR,
5037 "%s: ccmCfgSetInt failed for short retry count %hu",
5038 __func__, retry_value);
5039 return -EIO;
5040 }
5041 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
5042 __func__, retry_value);
5043 }
5044 }
5045
5046 return 0;
5047}
5048
5049/*
5050 * FUNCTION: wlan_hdd_cfg80211_set_txpower
5051 * This function is used to set the txpower
5052 */
5053static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
5054#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
5055 enum tx_power_setting type,
5056#else
5057 enum nl80211_tx_power_setting type,
5058#endif
5059 int dbm)
5060{
5061 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5062 tHalHandle hHal = pHddCtx->hHal;
5063 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5064 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5065
5066 ENTER();
5067
5068 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
5069 dbm, ccmCfgSetCallback,
5070 eANI_BOOLEAN_TRUE))
5071 {
5072 hddLog(VOS_TRACE_LEVEL_ERROR,
5073 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
5074 return -EIO;
5075 }
5076
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005077 if ( pHddCtx->isLogpInProgress )
5078 {
5079 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5080 "%s:LOGP in Progress. Ignore!!!", __func__);
5081 return -EAGAIN;
5082 }
5083
Jeff Johnson295189b2012-06-20 16:38:30 -07005084 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
5085 dbm);
5086
5087 switch(type)
5088 {
5089 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
5090 /* Fall through */
5091 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
5092 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
5093 {
5094 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
5095 __func__);
5096 return -EIO;
5097 }
5098 break;
5099 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
5100 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
5101 __func__);
5102 return -EOPNOTSUPP;
5103 break;
5104 default:
5105 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
5106 __func__, type);
5107 return -EIO;
5108 }
5109
5110 return 0;
5111}
5112
5113/*
5114 * FUNCTION: wlan_hdd_cfg80211_get_txpower
5115 * This function is used to read the txpower
5116 */
5117static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
5118{
5119
5120 hdd_adapter_t *pAdapter;
5121 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5122
Jeff Johnsone7245742012-09-05 17:12:55 -07005123 ENTER();
5124
Jeff Johnson295189b2012-06-20 16:38:30 -07005125 if (NULL == pHddCtx)
5126 {
5127 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
5128 *dbm = 0;
5129 return -ENOENT;
5130 }
5131
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005132 if ( pHddCtx->isLogpInProgress )
5133 {
5134 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5135 "%s:LOGP in Progress. Ignore!!!", __func__);
5136 return -EAGAIN;
5137 }
5138
Jeff Johnson295189b2012-06-20 16:38:30 -07005139 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5140 if (NULL == pAdapter)
5141 {
5142 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
5143 return -ENOENT;
5144 }
5145
5146 wlan_hdd_get_classAstats(pAdapter);
5147 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
5148
Jeff Johnsone7245742012-09-05 17:12:55 -07005149 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005150 return 0;
5151}
5152
5153static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
5154 u8* mac, struct station_info *sinfo)
5155{
5156 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5157 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5158 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
5159 tANI_U8 rate_flags;
5160
5161 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5162 hdd_config_t *pCfg = pHddCtx->cfg_ini;
5163 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5164
5165 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
5166 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
5167 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
5168 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
5169 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
5170 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
5171 tANI_U16 maxRate = 0;
5172 tANI_U16 myRate;
5173 tANI_U16 currentRate = 0;
5174 tANI_U8 maxSpeedMCS = 0;
5175 tANI_U8 maxMCSIdx = 0;
5176 tANI_U8 rateFlag = 1;
5177 tANI_U8 i, j, rssidx;
5178
Jeff Johnsone7245742012-09-05 17:12:55 -07005179 ENTER();
5180
Jeff Johnson295189b2012-06-20 16:38:30 -07005181 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
5182 (0 == ssidlen))
5183 {
5184 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
5185 " Invalid ssidlen, %d", __func__, ssidlen);
5186 /*To keep GUI happy*/
5187 return 0;
5188 }
5189
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005190 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5191 {
5192 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5193 "%s:LOGP in Progress. Ignore!!!", __func__);
5194 return -EAGAIN;
5195 }
5196
Jeff Johnson295189b2012-06-20 16:38:30 -07005197 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
5198 sinfo->filled |= STATION_INFO_SIGNAL;
5199
5200 wlan_hdd_get_classAstats(pAdapter);
5201 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
5202
5203 //convert to the UI units of 100kbps
5204 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
5205
5206#ifdef LINKSPEED_DEBUG_ENABLED
5207 pr_info("RSSI %d, RLMS %u, rate %d, rssi high %d, rssi low %d\n",
5208 sinfo->signal,
5209 pCfg->reportMaxLinkSpeed,
5210 myRate,
5211 (int) pCfg->linkSpeedRssiHigh,
5212 (int) pCfg->linkSpeedRssiLow);
5213#endif //LINKSPEED_DEBUG_ENABLED
5214
5215 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
5216 {
5217 // we do not want to necessarily report the current speed
5218 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
5219 {
5220 // report the max possible speed
5221 rssidx = 0;
5222 }
5223 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
5224 {
5225 // report the max possible speed with RSSI scaling
5226 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
5227 {
5228 // report the max possible speed
5229 rssidx = 0;
5230 }
5231 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
5232 {
5233 // report middle speed
5234 rssidx = 1;
5235 }
5236 else
5237 {
5238 // report actual speed
5239 rssidx = 2;
5240 }
5241 }
5242 else
5243 {
5244 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
5245 hddLog(VOS_TRACE_LEVEL_ERROR,
5246 "%s: Invalid value for reportMaxLinkSpeed: %u",
5247 __func__, pCfg->reportMaxLinkSpeed);
5248 rssidx = 0;
5249 }
5250
5251 maxRate = 0;
5252
5253 /* Get Basic Rate Set */
5254 ccmCfgGetStr(hHal, WNI_CFG_OPERATIONAL_RATE_SET, OperationalRates, &ORLeng);
5255 for (i = 0; i < ORLeng; i++)
5256 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005257 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005258 {
5259 /* Validate Rate Set */
5260 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
5261 {
5262 currentRate = supported_data_rate[j].supported_rate[rssidx];
5263 break;
5264 }
5265 }
5266 /* Update MAX rate */
5267 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5268 }
5269
5270 /* Get Extended Rate Set */
5271 ccmCfgGetStr(hHal, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, ExtendedRates, &ERLeng);
5272 for (i = 0; i < ERLeng; i++)
5273 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005274 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005275 {
5276 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
5277 {
5278 currentRate = supported_data_rate[j].supported_rate[rssidx];
5279 break;
5280 }
5281 }
5282 /* Update MAX rate */
5283 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5284 }
5285
5286 /* Get MCS Rate Set -- but only if we are connected at MCS
5287 rates or if we are always reporting max speed or if we have
5288 good rssi */
5289 if ((0 == rssidx) || !(rate_flags & eHAL_TX_RATE_LEGACY))
5290 {
5291 ccmCfgGetStr(hHal, WNI_CFG_CURRENT_MCS_SET, MCSRates, &MCSLeng);
5292 rateFlag = 0;
5293 if (rate_flags & eHAL_TX_RATE_HT40)
5294 {
5295 rateFlag |= 1;
5296 }
5297 if (rate_flags & eHAL_TX_RATE_SGI)
5298 {
5299 rateFlag |= 2;
5300 }
5301
5302 for (i = 0; i < MCSLeng; i++)
5303 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005304 for (j = 0; j < (sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0])); j++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005305 {
5306 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
5307 {
5308 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
5309 break;
5310 }
5311 }
5312 if (currentRate > maxRate)
5313 {
5314 maxRate = currentRate;
5315 maxSpeedMCS = 1;
5316 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
5317 }
5318 }
5319 }
5320
5321 // make sure we report a value at least as big as our current rate
5322 if (maxRate < myRate)
5323 {
5324 maxRate = myRate;
5325 if (rate_flags & eHAL_TX_RATE_LEGACY)
5326 {
5327 maxSpeedMCS = 0;
5328 }
5329 else
5330 {
5331 maxSpeedMCS = 1;
5332 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
5333 }
5334 }
5335
5336 if (!maxSpeedMCS)
5337 {
5338 sinfo->txrate.legacy = maxRate;
5339#ifdef LINKSPEED_DEBUG_ENABLED
5340 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
5341#endif //LINKSPEED_DEBUG_ENABLED
5342 }
5343 else
5344 {
5345 sinfo->txrate.mcs = maxMCSIdx;
5346 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
5347 if (rate_flags & eHAL_TX_RATE_SGI)
5348 {
5349 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
5350 }
5351 if (rate_flags & eHAL_TX_RATE_HT40)
5352 {
5353 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
5354 }
5355#ifdef LINKSPEED_DEBUG_ENABLED
5356 pr_info("Reporting MCS rate %d flags %x\n",
5357 sinfo->txrate.mcs,
5358 sinfo->txrate.flags );
5359#endif //LINKSPEED_DEBUG_ENABLED
5360 }
5361 }
5362 else
5363 {
5364 // report current rate instead of max rate
5365
5366 if (rate_flags & eHAL_TX_RATE_LEGACY)
5367 {
5368 //provide to the UI in units of 100kbps
5369 sinfo->txrate.legacy = myRate;
5370#ifdef LINKSPEED_DEBUG_ENABLED
5371 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
5372#endif //LINKSPEED_DEBUG_ENABLED
5373 }
5374 else
5375 {
5376 //must be MCS
5377 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
5378 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
5379 if (rate_flags & eHAL_TX_RATE_SGI)
5380 {
5381 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
5382 }
5383 if (rate_flags & eHAL_TX_RATE_HT40)
5384 {
5385 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
5386 }
5387#ifdef LINKSPEED_DEBUG_ENABLED
5388 pr_info("Reporting actual MCS rate %d flags %x\n",
5389 sinfo->txrate.mcs,
5390 sinfo->txrate.flags );
5391#endif //LINKSPEED_DEBUG_ENABLED
5392 }
5393 }
5394 sinfo->filled |= STATION_INFO_TX_BITRATE;
5395
Jeff Johnsone7245742012-09-05 17:12:55 -07005396 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005397 return 0;
5398}
5399
5400static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
5401 struct net_device *dev, bool mode, v_SINT_t timeout)
5402{
5403 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5404 VOS_STATUS vos_status;
5405
Jeff Johnsone7245742012-09-05 17:12:55 -07005406 ENTER();
5407
Jeff Johnson295189b2012-06-20 16:38:30 -07005408 if (NULL == pAdapter)
5409 {
5410 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
5411 return -ENODEV;
5412 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005413 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5414 {
5415 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5416 "%s:LOGP in Progress. Ignore!!!", __func__);
5417 return -EAGAIN;
5418 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005419
5420 /**The get power cmd from the supplicant gets updated by the nl only
5421 *on successful execution of the function call
5422 *we are oppositely mapped w.r.t mode in the driver
5423 **/
5424 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
5425
Jeff Johnsone7245742012-09-05 17:12:55 -07005426 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005427 if (VOS_STATUS_E_FAILURE == vos_status)
5428 {
5429 return -EINVAL;
5430 }
5431 return 0;
5432}
5433
5434
5435#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5436static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
5437 struct net_device *netdev,
5438 u8 key_index)
5439{
Jeff Johnsone7245742012-09-05 17:12:55 -07005440 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005441 return 0;
5442}
5443#endif //LINUX_VERSION_CODE
5444
5445#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
5446static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
5447 struct net_device *dev,
5448 struct ieee80211_txq_params *params)
5449{
Jeff Johnsone7245742012-09-05 17:12:55 -07005450 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005451 return 0;
5452}
5453#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5454static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
5455 struct ieee80211_txq_params *params)
5456{
Jeff Johnsone7245742012-09-05 17:12:55 -07005457 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005458 return 0;
5459}
5460#endif //LINUX_VERSION_CODE
5461
5462static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
5463 struct net_device *dev, u8 *mac)
5464{
5465 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5466
Jeff Johnsone7245742012-09-05 17:12:55 -07005467 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005468 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
5469 {
5470 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
5471 return -EINVAL;
5472 }
5473
5474 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
5475 {
5476 hddLog( LOGE,
5477 "%s: Wlan Load/Unload is in progress", __func__);
5478 return -EBUSY;
5479 }
5480
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005481 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5482 {
5483 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5484 "%s:LOGP in Progress. Ignore!!!", __func__);
5485 return -EAGAIN;
5486 }
5487
Jeff Johnson295189b2012-06-20 16:38:30 -07005488 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
5489#ifdef WLAN_FEATURE_P2P
5490 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
5491#endif
5492 )
5493 {
5494 if( NULL == mac )
5495 {
5496 v_U16_t i;
5497 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
5498 {
5499 if(pAdapter->aStaInfo[i].isUsed)
5500 {
5501 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
5502 hddLog(VOS_TRACE_LEVEL_INFO,
5503 "%s: Delete STA with MAC::"
5504 "%02x:%02x:%02x:%02x:%02x:%02x",
5505 __func__,
5506 macAddr[0], macAddr[1], macAddr[2],
5507 macAddr[3], macAddr[4], macAddr[5]);
5508 hdd_softap_sta_deauth(pAdapter, macAddr);
5509 }
5510 }
5511 }
5512 else
5513 {
5514 hddLog(VOS_TRACE_LEVEL_INFO,
5515 "%s: Delete STA with MAC::"
5516 "%02x:%02x:%02x:%02x:%02x:%02x",
5517 __func__,
5518 mac[0], mac[1], mac[2],
5519 mac[3], mac[4], mac[5]);
5520 hdd_softap_sta_deauth(pAdapter, mac);
5521 }
5522 }
5523
5524 EXIT();
5525
5526 return 0;
5527}
5528
5529static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
5530 struct net_device *dev, u8 *mac, struct station_parameters *params)
5531{
5532 // TODO: Implement this later.
Jeff Johnsone7245742012-09-05 17:12:55 -07005533 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005534 return 0;
5535}
5536
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005537
5538#ifdef FEATURE_WLAN_LFR
5539static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07005540 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005541{
5542#define MAX_PMKSAIDS_IN_CACHE 8
5543 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
5544 static tANI_U32 i = 0; // HDD Local Cache index
5545 tANI_U32 j=0;
5546 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5547 tHalHandle halHandle;
5548 eHalStatus result;
5549 tANI_U8 BSSIDMatched = 0;
5550
Jeff Johnsone7245742012-09-05 17:12:55 -07005551 ENTER();
5552
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005553 // Validate pAdapter
5554 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
5555 {
5556 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
5557 return -EINVAL;
5558 }
5559
5560 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
5561 {
5562 hddLog( LOGE,
5563 "%s: Wlan Load/Unload is in progress", __func__);
5564 return -EBUSY;
5565 }
5566
5567 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5568 {
5569 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5570 "%s:LOGP in Progress. Ignore!!!", __func__);
5571 return -EAGAIN;
5572 }
5573
5574 // Retrieve halHandle
5575 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
5576
5577 for (j = 0; j < i; j++)
5578 {
5579 if(vos_mem_compare(PMKIDCache[j].BSSID,
5580 pmksa->bssid, WNI_CFG_BSSID_LEN))
5581 {
5582 /* BSSID matched previous entry. Overwrite it. */
5583 BSSIDMatched = 1;
5584 vos_mem_copy(PMKIDCache[j].BSSID,
5585 pmksa->bssid, WNI_CFG_BSSID_LEN);
5586 vos_mem_copy(PMKIDCache[j].PMKID,
5587 pmksa->pmkid,
5588 CSR_RSN_PMKID_SIZE);
5589 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
5590 __FUNCTION__, j );
5591 dump_bssid(pmksa->bssid);
5592 dump_pmkid(halHandle, pmksa->pmkid);
5593 break;
5594 }
5595 }
5596
5597 if (!BSSIDMatched)
5598 {
5599 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
5600 vos_mem_copy(PMKIDCache[i].BSSID,
5601 pmksa->bssid, ETHER_ADDR_LEN);
5602 vos_mem_copy(PMKIDCache[i].PMKID,
5603 pmksa->pmkid,
5604 CSR_RSN_PMKID_SIZE);
5605 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
5606 __FUNCTION__, i );
5607 dump_bssid(pmksa->bssid);
5608 dump_pmkid(halHandle, pmksa->pmkid);
5609 // Increment the HDD Local Cache index
5610 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
5611 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
5612 }
5613
5614
5615 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
5616 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
5617 // __FUNCTION__, i );
5618 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
5619 __FUNCTION__, i );
5620 // Finally set the PMKSA ID Cache in CSR
5621 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
5622 PMKIDCache,
5623 i );
5624 return 0;
5625}
5626
5627
5628static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07005629 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005630{
Jeff Johnsone7245742012-09-05 17:12:55 -07005631 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005632 // TODO: Implement this later.
5633 return 0;
5634}
5635
5636static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
5637{
Jeff Johnsone7245742012-09-05 17:12:55 -07005638 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005639 // TODO: Implement this later.
5640 return 0;
5641}
5642#endif
5643
5644
Jeff Johnson295189b2012-06-20 16:38:30 -07005645/* cfg80211_ops */
5646static struct cfg80211_ops wlan_hdd_cfg80211_ops =
5647{
5648 .add_virtual_intf = wlan_hdd_add_virtual_intf,
5649 .del_virtual_intf = wlan_hdd_del_virtual_intf,
5650 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
5651 .change_station = wlan_hdd_change_station,
5652#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
5653 .add_beacon = wlan_hdd_cfg80211_add_beacon,
5654 .del_beacon = wlan_hdd_cfg80211_del_beacon,
5655 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005656#else
5657 .start_ap = wlan_hdd_cfg80211_start_ap,
5658 .change_beacon = wlan_hdd_cfg80211_change_beacon,
5659 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07005660#endif
5661 .change_bss = wlan_hdd_cfg80211_change_bss,
5662 .add_key = wlan_hdd_cfg80211_add_key,
5663 .get_key = wlan_hdd_cfg80211_get_key,
5664 .del_key = wlan_hdd_cfg80211_del_key,
5665 .set_default_key = wlan_hdd_cfg80211_set_default_key,
5666 .set_channel = wlan_hdd_cfg80211_set_channel,
5667 .scan = wlan_hdd_cfg80211_scan,
5668 .connect = wlan_hdd_cfg80211_connect,
5669 .disconnect = wlan_hdd_cfg80211_disconnect,
5670 .join_ibss = wlan_hdd_cfg80211_join_ibss,
5671 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
5672 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
5673 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
5674 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
5675#ifdef WLAN_FEATURE_P2P
5676 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
5677 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
5678 .mgmt_tx = wlan_hdd_action,
5679#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5680 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
5681 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
5682 .set_txq_params = wlan_hdd_set_txq_params,
5683#endif
5684#endif
5685 .get_station = wlan_hdd_cfg80211_get_station,
5686 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
5687 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005688 .add_station = wlan_hdd_cfg80211_add_station,
5689#ifdef FEATURE_WLAN_LFR
5690 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
5691 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
5692 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
5693#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005694};
5695
5696#endif // CONFIG_CFG80211