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