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