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