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