staging: wilc1000: remove spi_max_speed of wilc_wlan_io_func_t
[deliverable/linux.git] / drivers / staging / wilc1000 / wilc_wfi_cfgoperations.c
CommitLineData
c5c77ba1
JK
1/*!
2 * @file wilc_wfi_cfgopertaions.c
3 * @brief CFG80211 Function Implementation functionality
4 * @author aabouzaeid
5 * mabubakr
6 * mdaftedar
7 * zsalah
8 * @sa wilc_wfi_cfgopertaions.h top level OS wrapper file
9 * @date 31 Aug 2010
10 * @version 1.0
11 */
12
13#include "wilc_wfi_cfgoperations.h"
c5c77ba1 14#ifdef WILC_SDIO
cdc9cba5 15#include "linux_wlan_sdio.h"
c5c77ba1 16#endif
7ae43363 17#include <linux/errno.h>
c5c77ba1
JK
18
19#define IS_MANAGMEMENT 0x100
20#define IS_MANAGMEMENT_CALLBACK 0x080
21#define IS_MGMT_STATUS_SUCCES 0x040
22#define GET_PKT_OFFSET(a) (((a) >> 22) & 0x1ff)
23
c5c77ba1
JK
24extern int mac_open(struct net_device *ndev);
25extern int mac_close(struct net_device *ndev);
26
27tstrNetworkInfo astrLastScannedNtwrksShadow[MAX_NUM_SCANNED_NETWORKS_SHADOW];
4e4467fd 28u32 u32LastScannedNtwrksCountShadow;
da711eb6 29struct timer_list hDuringIpTimer;
da711eb6 30struct timer_list hAgingTimer;
63d03e47
GKH
31static u8 op_ifcs;
32extern u8 u8ConnectedSSID[6];
c5c77ba1 33
63d03e47 34u8 g_wilc_initialized = 1;
72ed4dc7 35extern bool g_obtainingIP;
c5c77ba1
JK
36
37#define CHAN2G(_channel, _freq, _flags) { \
38 .band = IEEE80211_BAND_2GHZ, \
39 .center_freq = (_freq), \
40 .hw_value = (_channel), \
41 .flags = (_flags), \
42 .max_antenna_gain = 0, \
43 .max_power = 30, \
44}
45
46/*Frequency range for channels*/
47static struct ieee80211_channel WILC_WFI_2ghz_channels[] = {
48 CHAN2G(1, 2412, 0),
49 CHAN2G(2, 2417, 0),
50 CHAN2G(3, 2422, 0),
51 CHAN2G(4, 2427, 0),
52 CHAN2G(5, 2432, 0),
53 CHAN2G(6, 2437, 0),
54 CHAN2G(7, 2442, 0),
55 CHAN2G(8, 2447, 0),
56 CHAN2G(9, 2452, 0),
57 CHAN2G(10, 2457, 0),
58 CHAN2G(11, 2462, 0),
59 CHAN2G(12, 2467, 0),
60 CHAN2G(13, 2472, 0),
61 CHAN2G(14, 2484, 0),
62};
63
64#define RATETAB_ENT(_rate, _hw_value, _flags) { \
65 .bitrate = (_rate), \
66 .hw_value = (_hw_value), \
67 .flags = (_flags), \
68}
69
70
71/* Table 6 in section 3.2.1.1 */
72static struct ieee80211_rate WILC_WFI_rates[] = {
73 RATETAB_ENT(10, 0, 0),
74 RATETAB_ENT(20, 1, 0),
75 RATETAB_ENT(55, 2, 0),
76 RATETAB_ENT(110, 3, 0),
77 RATETAB_ENT(60, 9, 0),
78 RATETAB_ENT(90, 6, 0),
79 RATETAB_ENT(120, 7, 0),
80 RATETAB_ENT(180, 8, 0),
81 RATETAB_ENT(240, 9, 0),
82 RATETAB_ENT(360, 10, 0),
83 RATETAB_ENT(480, 11, 0),
84 RATETAB_ENT(540, 12, 0),
85};
86
c5c77ba1
JK
87struct p2p_mgmt_data {
88 int size;
89 u8 *buff;
90};
91
92/*Global variable used to state the current connected STA channel*/
63d03e47 93u8 u8WLANChannel = INVALID_CHANNEL;
c5c77ba1 94
866a2c24 95u8 curr_channel;
c5c77ba1 96
63d03e47
GKH
97u8 u8P2P_oui[] = {0x50, 0x6f, 0x9A, 0x09};
98u8 u8P2Plocalrandom = 0x01;
99u8 u8P2Precvrandom = 0x00;
100u8 u8P2P_vendorspec[] = {0xdd, 0x05, 0x00, 0x08, 0x40, 0x03};
7fc80964 101bool bWilc_ie;
c5c77ba1
JK
102
103static struct ieee80211_supported_band WILC_WFI_band_2ghz = {
104 .channels = WILC_WFI_2ghz_channels,
105 .n_channels = ARRAY_SIZE(WILC_WFI_2ghz_channels),
106 .bitrates = WILC_WFI_rates,
107 .n_bitrates = ARRAY_SIZE(WILC_WFI_rates),
108};
109
110
c5c77ba1
JK
111struct add_key_params {
112 u8 key_idx;
c5c77ba1 113 bool pairwise;
c5c77ba1
JK
114 u8 *mac_addr;
115};
116struct add_key_params g_add_gtk_key_params;
117struct wilc_wfi_key g_key_gtk_params;
118struct add_key_params g_add_ptk_key_params;
119struct wilc_wfi_key g_key_ptk_params;
120struct wilc_wfi_wep_key g_key_wep_params;
7fc80964
DM
121bool g_ptk_keys_saved;
122bool g_gtk_keys_saved;
123bool g_wep_keys_saved;
c5c77ba1
JK
124
125#define AGING_TIME (9 * 1000)
126#define duringIP_TIME 15000
127
128void clear_shadow_scan(void *pUserVoid)
129{
c5c77ba1 130 int i;
8dfaafd6 131
c5c77ba1 132 if (op_ifcs == 0) {
4183e979 133 del_timer_sync(&hAgingTimer);
c5c77ba1
JK
134 PRINT_INFO(CORECONFIG_DBG, "destroy aging timer\n");
135
136 for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
137 if (astrLastScannedNtwrksShadow[u32LastScannedNtwrksCountShadow].pu8IEs != NULL) {
49188af2 138 kfree(astrLastScannedNtwrksShadow[i].pu8IEs);
c5c77ba1
JK
139 astrLastScannedNtwrksShadow[u32LastScannedNtwrksCountShadow].pu8IEs = NULL;
140 }
141
142 host_int_freeJoinParams(astrLastScannedNtwrksShadow[i].pJoinParams);
143 astrLastScannedNtwrksShadow[i].pJoinParams = NULL;
144 }
145 u32LastScannedNtwrksCountShadow = 0;
146 }
147
148}
149
fbc2fe16 150u32 get_rssi_avg(tstrNetworkInfo *pstrNetworkInfo)
c5c77ba1 151{
51e825f7 152 u8 i;
c5c77ba1 153 int rssi_v = 0;
51e825f7 154 u8 num_rssi = (pstrNetworkInfo->strRssi.u8Full) ? NUM_RSSI : (pstrNetworkInfo->strRssi.u8Index);
c5c77ba1
JK
155
156 for (i = 0; i < num_rssi; i++)
157 rssi_v += pstrNetworkInfo->strRssi.as8RSSI[i];
158
159 rssi_v /= num_rssi;
160 return rssi_v;
161}
162
51e825f7 163void refresh_scan(void *pUserVoid, u8 all, bool bDirectScan)
c5c77ba1 164{
2726887c 165 struct wilc_priv *priv;
c5c77ba1
JK
166 struct wiphy *wiphy;
167 struct cfg80211_bss *bss = NULL;
168 int i;
169 int rssi = 0;
170
2726887c 171 priv = (struct wilc_priv *)pUserVoid;
c5c77ba1
JK
172 wiphy = priv->dev->ieee80211_ptr->wiphy;
173
174 for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
175 tstrNetworkInfo *pstrNetworkInfo;
8dfaafd6 176
c5c77ba1
JK
177 pstrNetworkInfo = &(astrLastScannedNtwrksShadow[i]);
178
179
180 if ((!pstrNetworkInfo->u8Found) || all) {
fb4ec9ca 181 s32 s32Freq;
c5c77ba1
JK
182 struct ieee80211_channel *channel;
183
b1413b60 184 if (pstrNetworkInfo != NULL) {
c5c77ba1 185
fb4ec9ca 186 s32Freq = ieee80211_channel_to_frequency((s32)pstrNetworkInfo->u8channel, IEEE80211_BAND_2GHZ);
c5c77ba1
JK
187 channel = ieee80211_get_channel(wiphy, s32Freq);
188
189 rssi = get_rssi_avg(pstrNetworkInfo);
1a646e7e 190 if (memcmp("DIRECT-", pstrNetworkInfo->au8ssid, 7) || bDirectScan) {
c5c77ba1
JK
191 bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, pstrNetworkInfo->au8bssid, pstrNetworkInfo->u64Tsf, pstrNetworkInfo->u16CapInfo,
192 pstrNetworkInfo->u16BeaconPeriod, (const u8 *)pstrNetworkInfo->pu8IEs,
fb4ec9ca 193 (size_t)pstrNetworkInfo->u16IEsLen, (((s32)rssi) * 100), GFP_KERNEL);
c5c77ba1 194 cfg80211_put_bss(wiphy, bss);
c5c77ba1
JK
195 }
196 }
197
198 }
199 }
200
201}
202
203void reset_shadow_found(void *pUserVoid)
204{
c5c77ba1 205 int i;
8dfaafd6 206
c5c77ba1
JK
207 for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
208 astrLastScannedNtwrksShadow[i].u8Found = 0;
209
210 }
211}
212
213void update_scan_time(void *pUserVoid)
214{
c5c77ba1 215 int i;
8dfaafd6 216
c5c77ba1
JK
217 for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
218 astrLastScannedNtwrksShadow[i].u32TimeRcvdInScan = jiffies;
219 }
220}
221
93dee8ee 222static void remove_network_from_shadow(unsigned long arg)
c5c77ba1 223{
c5c77ba1
JK
224 unsigned long now = jiffies;
225 int i, j;
226
c5c77ba1
JK
227
228 for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
229 if (time_after(now, astrLastScannedNtwrksShadow[i].u32TimeRcvdInScan + (unsigned long)(SCAN_RESULT_EXPIRE))) {
17aacd43 230 PRINT_D(CFG80211_DBG, "Network expired in ScanShadow: %s\n", astrLastScannedNtwrksShadow[i].au8ssid);
c5c77ba1 231
cccfc39e
SB
232 kfree(astrLastScannedNtwrksShadow[i].pu8IEs);
233 astrLastScannedNtwrksShadow[i].pu8IEs = NULL;
c5c77ba1
JK
234
235 host_int_freeJoinParams(astrLastScannedNtwrksShadow[i].pJoinParams);
236
237 for (j = i; (j < u32LastScannedNtwrksCountShadow - 1); j++) {
238 astrLastScannedNtwrksShadow[j] = astrLastScannedNtwrksShadow[j + 1];
239 }
240 u32LastScannedNtwrksCountShadow--;
241 }
242 }
243
244 PRINT_D(CFG80211_DBG, "Number of cached networks: %d\n", u32LastScannedNtwrksCountShadow);
9eb06643
GKH
245 if (u32LastScannedNtwrksCountShadow != 0) {
246 hAgingTimer.data = arg;
247 mod_timer(&hAgingTimer, jiffies + msecs_to_jiffies(AGING_TIME));
248 } else {
c5c77ba1 249 PRINT_D(CFG80211_DBG, "No need to restart Aging timer\n");
9eb06643 250 }
c5c77ba1
JK
251}
252
93dee8ee 253static void clear_duringIP(unsigned long arg)
c5c77ba1
JK
254{
255 PRINT_D(GENERIC_DBG, "GO:IP Obtained , enable scan\n");
72ed4dc7 256 g_obtainingIP = false;
c5c77ba1 257}
c5c77ba1 258
a74cc6b8 259int is_network_in_shadow(tstrNetworkInfo *pstrNetworkInfo, void *pUserVoid)
c5c77ba1 260{
a74cc6b8 261 int state = -1;
c5c77ba1
JK
262 int i;
263
c5c77ba1
JK
264 if (u32LastScannedNtwrksCountShadow == 0) {
265 PRINT_D(CFG80211_DBG, "Starting Aging timer\n");
9eb06643
GKH
266 hAgingTimer.data = (unsigned long)pUserVoid;
267 mod_timer(&hAgingTimer, jiffies + msecs_to_jiffies(AGING_TIME));
c5c77ba1
JK
268 state = -1;
269 } else {
270 /* Linear search for now */
271 for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
1a646e7e 272 if (memcmp(astrLastScannedNtwrksShadow[i].au8bssid,
c5c77ba1
JK
273 pstrNetworkInfo->au8bssid, 6) == 0) {
274 state = i;
275 break;
276 }
277 }
278 }
279 return state;
280}
281
282void add_network_to_shadow(tstrNetworkInfo *pstrNetworkInfo, void *pUserVoid, void *pJoinParams)
283{
a74cc6b8 284 int ap_found = is_network_in_shadow(pstrNetworkInfo, pUserVoid);
fbc2fe16 285 u32 ap_index = 0;
51e825f7 286 u8 rssi_index = 0;
c5c77ba1
JK
287
288 if (u32LastScannedNtwrksCountShadow >= MAX_NUM_SCANNED_NETWORKS_SHADOW) {
289 PRINT_D(CFG80211_DBG, "Shadow network reached its maximum limit\n");
290 return;
291 }
292 if (ap_found == -1) {
293 ap_index = u32LastScannedNtwrksCountShadow;
294 u32LastScannedNtwrksCountShadow++;
295
296 } else {
297 ap_index = ap_found;
298 }
299 rssi_index = astrLastScannedNtwrksShadow[ap_index].strRssi.u8Index;
300 astrLastScannedNtwrksShadow[ap_index].strRssi.as8RSSI[rssi_index++] = pstrNetworkInfo->s8rssi;
301 if (rssi_index == NUM_RSSI) {
302 rssi_index = 0;
303 astrLastScannedNtwrksShadow[ap_index].strRssi.u8Full = 1;
304 }
305 astrLastScannedNtwrksShadow[ap_index].strRssi.u8Index = rssi_index;
306
307 astrLastScannedNtwrksShadow[ap_index].s8rssi = pstrNetworkInfo->s8rssi;
308 astrLastScannedNtwrksShadow[ap_index].u16CapInfo = pstrNetworkInfo->u16CapInfo;
309
310 astrLastScannedNtwrksShadow[ap_index].u8SsidLen = pstrNetworkInfo->u8SsidLen;
d00d2ba3 311 memcpy(astrLastScannedNtwrksShadow[ap_index].au8ssid,
c5c77ba1
JK
312 pstrNetworkInfo->au8ssid, pstrNetworkInfo->u8SsidLen);
313
d00d2ba3 314 memcpy(astrLastScannedNtwrksShadow[ap_index].au8bssid,
c5c77ba1
JK
315 pstrNetworkInfo->au8bssid, ETH_ALEN);
316
317 astrLastScannedNtwrksShadow[ap_index].u16BeaconPeriod = pstrNetworkInfo->u16BeaconPeriod;
318 astrLastScannedNtwrksShadow[ap_index].u8DtimPeriod = pstrNetworkInfo->u8DtimPeriod;
319 astrLastScannedNtwrksShadow[ap_index].u8channel = pstrNetworkInfo->u8channel;
320
321 astrLastScannedNtwrksShadow[ap_index].u16IEsLen = pstrNetworkInfo->u16IEsLen;
322 astrLastScannedNtwrksShadow[ap_index].u64Tsf = pstrNetworkInfo->u64Tsf;
323 if (ap_found != -1)
49188af2 324 kfree(astrLastScannedNtwrksShadow[ap_index].pu8IEs);
c5c77ba1 325 astrLastScannedNtwrksShadow[ap_index].pu8IEs =
f3052587 326 kmalloc(pstrNetworkInfo->u16IEsLen, GFP_KERNEL); /* will be deallocated by the WILC_WFI_CfgScan() function */
d00d2ba3 327 memcpy(astrLastScannedNtwrksShadow[ap_index].pu8IEs,
c5c77ba1
JK
328 pstrNetworkInfo->pu8IEs, pstrNetworkInfo->u16IEsLen);
329
330 astrLastScannedNtwrksShadow[ap_index].u32TimeRcvdInScan = jiffies;
331 astrLastScannedNtwrksShadow[ap_index].u32TimeRcvdInScanCached = jiffies;
332 astrLastScannedNtwrksShadow[ap_index].u8Found = 1;
333 if (ap_found != -1)
334 host_int_freeJoinParams(astrLastScannedNtwrksShadow[ap_index].pJoinParams);
335 astrLastScannedNtwrksShadow[ap_index].pJoinParams = pJoinParams;
336
337}
338
339
340/**
341 * @brief CfgScanResult
342 * @details Callback function which returns the scan results found
343 *
344 * @param[in] tenuScanEvent enuScanEvent: enum, indicating the scan event triggered, whether that is
345 * SCAN_EVENT_NETWORK_FOUND or SCAN_EVENT_DONE
346 * tstrNetworkInfo* pstrNetworkInfo: structure holding the scan results information
347 * void* pUserVoid: Private structure associated with the wireless interface
348 * @return NONE
349 * @author mabubakr
350 * @date
351 * @version 1.0
352 */
1ec3815f 353static void CfgScanResult(enum scan_event enuScanEvent, tstrNetworkInfo *pstrNetworkInfo, void *pUserVoid, void *pJoinParams)
c5c77ba1 354{
2726887c 355 struct wilc_priv *priv;
c5c77ba1 356 struct wiphy *wiphy;
fb4ec9ca 357 s32 s32Freq;
c5c77ba1 358 struct ieee80211_channel *channel;
c5c77ba1
JK
359 struct cfg80211_bss *bss = NULL;
360
2726887c 361 priv = (struct wilc_priv *)pUserVoid;
7e4e87d3 362 if (priv->bCfgScanning) {
c5c77ba1
JK
363 if (enuScanEvent == SCAN_EVENT_NETWORK_FOUND) {
364 wiphy = priv->dev->ieee80211_ptr->wiphy;
7ae43363
LK
365
366 if (!wiphy)
367 return;
368
c5c77ba1
JK
369 if (wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC
370 &&
fb4ec9ca 371 ((((s32)pstrNetworkInfo->s8rssi) * 100) < 0
c5c77ba1 372 ||
fb4ec9ca 373 (((s32)pstrNetworkInfo->s8rssi) * 100) > 100)
c5c77ba1 374 ) {
24db713f
LK
375 PRINT_ER("wiphy signal type fial\n");
376 return;
c5c77ba1
JK
377 }
378
b1413b60 379 if (pstrNetworkInfo != NULL) {
fb4ec9ca 380 s32Freq = ieee80211_channel_to_frequency((s32)pstrNetworkInfo->u8channel, IEEE80211_BAND_2GHZ);
c5c77ba1
JK
381 channel = ieee80211_get_channel(wiphy, s32Freq);
382
7ae43363
LK
383 if (!channel)
384 return;
c5c77ba1
JK
385
386 PRINT_INFO(CFG80211_DBG, "Network Info:: CHANNEL Frequency: %d, RSSI: %d, CapabilityInfo: %d,"
17aacd43 387 "BeaconPeriod: %d\n", channel->center_freq, (((s32)pstrNetworkInfo->s8rssi) * 100),
c5c77ba1
JK
388 pstrNetworkInfo->u16CapInfo, pstrNetworkInfo->u16BeaconPeriod);
389
7e4e87d3 390 if (pstrNetworkInfo->bNewNetwork) {
c5c77ba1
JK
391 if (priv->u32RcvdChCount < MAX_NUM_SCANNED_NETWORKS) { /* TODO: mostafa: to be replaced by */
392 /* max_scan_ssids */
393 PRINT_D(CFG80211_DBG, "Network %s found\n", pstrNetworkInfo->au8ssid);
394
395
396 priv->u32RcvdChCount++;
397
398
399
400 if (pJoinParams == NULL) {
401 PRINT_INFO(CORECONFIG_DBG, ">> Something really bad happened\n");
402 }
403 add_network_to_shadow(pstrNetworkInfo, priv, pJoinParams);
404
405 /*P2P peers are sent to WPA supplicant and added to shadow table*/
406
1a646e7e 407 if (!(memcmp("DIRECT-", pstrNetworkInfo->au8ssid, 7))) {
c5c77ba1
JK
408 bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, pstrNetworkInfo->au8bssid, pstrNetworkInfo->u64Tsf, pstrNetworkInfo->u16CapInfo,
409 pstrNetworkInfo->u16BeaconPeriod, (const u8 *)pstrNetworkInfo->pu8IEs,
fb4ec9ca 410 (size_t)pstrNetworkInfo->u16IEsLen, (((s32)pstrNetworkInfo->s8rssi) * 100), GFP_KERNEL);
c5c77ba1 411 cfg80211_put_bss(wiphy, bss);
c5c77ba1
JK
412 }
413
414
415 } else {
416 PRINT_ER("Discovered networks exceeded the max limit\n");
417 }
418 } else {
4e4467fd 419 u32 i;
c5c77ba1
JK
420 /* So this network is discovered before, we'll just update its RSSI */
421 for (i = 0; i < priv->u32RcvdChCount; i++) {
1a646e7e 422 if (memcmp(astrLastScannedNtwrksShadow[i].au8bssid, pstrNetworkInfo->au8bssid, 6) == 0) {
17aacd43 423 PRINT_D(CFG80211_DBG, "Update RSSI of %s\n", astrLastScannedNtwrksShadow[i].au8ssid);
c5c77ba1
JK
424
425 astrLastScannedNtwrksShadow[i].s8rssi = pstrNetworkInfo->s8rssi;
426 astrLastScannedNtwrksShadow[i].u32TimeRcvdInScan = jiffies;
427 break;
428 }
429 }
430 }
431 }
432 } else if (enuScanEvent == SCAN_EVENT_DONE) {
17aacd43
CG
433 PRINT_D(CFG80211_DBG, "Scan Done[%p]\n", priv->dev);
434 PRINT_D(CFG80211_DBG, "Refreshing Scan ...\n");
72ed4dc7 435 refresh_scan(priv, 1, false);
c5c77ba1 436
78174ada 437 if (priv->u32RcvdChCount > 0)
17aacd43 438 PRINT_D(CFG80211_DBG, "%d Network(s) found\n", priv->u32RcvdChCount);
78174ada 439 else
17aacd43 440 PRINT_D(CFG80211_DBG, "No networks found\n");
c5c77ba1 441
83383ea3 442 down(&(priv->hSemScanReq));
c5c77ba1 443
b1413b60 444 if (priv->pstrScanReq != NULL) {
72ed4dc7 445 cfg80211_scan_done(priv->pstrScanReq, false);
c5c77ba1 446 priv->u32RcvdChCount = 0;
72ed4dc7 447 priv->bCfgScanning = false;
b1413b60 448 priv->pstrScanReq = NULL;
c5c77ba1 449 }
83383ea3 450 up(&(priv->hSemScanReq));
c5c77ba1
JK
451
452 }
453 /*Aborting any scan operation during mac close*/
454 else if (enuScanEvent == SCAN_EVENT_ABORTED) {
83383ea3 455 down(&(priv->hSemScanReq));
c5c77ba1 456
17aacd43 457 PRINT_D(CFG80211_DBG, "Scan Aborted\n");
b1413b60 458 if (priv->pstrScanReq != NULL) {
c5c77ba1
JK
459
460 update_scan_time(priv);
72ed4dc7 461 refresh_scan(priv, 1, false);
c5c77ba1 462
72ed4dc7
DL
463 cfg80211_scan_done(priv->pstrScanReq, false);
464 priv->bCfgScanning = false;
b1413b60 465 priv->pstrScanReq = NULL;
c5c77ba1 466 }
83383ea3 467 up(&(priv->hSemScanReq));
c5c77ba1
JK
468 }
469 }
c5c77ba1
JK
470}
471
472
473/**
474 * @brief WILC_WFI_Set_PMKSA
475 * @details Check if pmksa is cached and set it.
476 * @param[in]
477 * @return int : Return 0 on Success
478 * @author mdaftedar
479 * @date 01 MAR 2012
480 * @version 1.0
481 */
2726887c 482int WILC_WFI_Set_PMKSA(u8 *bssid, struct wilc_priv *priv)
c5c77ba1 483{
4e4467fd 484 u32 i;
e6e12661 485 s32 s32Error = 0;
c5c77ba1
JK
486
487
488 for (i = 0; i < priv->pmkid_list.numpmkid; i++) {
489
1a646e7e 490 if (!memcmp(bssid, priv->pmkid_list.pmkidlist[i].bssid,
c5c77ba1
JK
491 ETH_ALEN)) {
492 PRINT_D(CFG80211_DBG, "PMKID successful comparison");
493
494 /*If bssid is found, set the values*/
495 s32Error = host_int_set_pmkid_info(priv->hWILCWFIDrv, &priv->pmkid_list);
496
e6e12661 497 if (s32Error != 0)
c5c77ba1
JK
498 PRINT_ER("Error in pmkid\n");
499
500 break;
501 }
502 }
503
504 return s32Error;
505
506
507}
c5c77ba1
JK
508
509/**
510 * @brief CfgConnectResult
511 * @details
512 * @param[in] tenuConnDisconnEvent enuConnDisconnEvent: Type of connection response either
513 * connection response or disconnection notification.
514 * tstrConnectInfo* pstrConnectInfo: COnnection information.
63d03e47 515 * u8 u8MacStatus: Mac Status from firmware
c5c77ba1
JK
516 * tstrDisconnectNotifInfo* pstrDisconnectNotifInfo: Disconnection Notification
517 * void* pUserVoid: Private data associated with wireless interface
518 * @return NONE
519 * @author mabubakr
520 * @date 01 MAR 2012
521 * @version 1.0
522 */
523int connecting;
524
ed3f0379 525static void CfgConnectResult(enum conn_event enuConnDisconnEvent,
c5c77ba1 526 tstrConnectInfo *pstrConnectInfo,
63d03e47 527 u8 u8MacStatus,
c5c77ba1
JK
528 tstrDisconnectNotifInfo *pstrDisconnectNotifInfo,
529 void *pUserVoid)
530{
2726887c 531 struct wilc_priv *priv;
c5c77ba1 532 struct net_device *dev;
441dc609 533 struct host_if_drv *pstrWFIDrv;
63d03e47 534 u8 NullBssid[ETH_ALEN] = {0};
c1ec2c12
GL
535 struct wilc *wl;
536 perInterface_wlan_t *nic;
8dfaafd6 537
c5c77ba1
JK
538 connecting = 0;
539
2726887c 540 priv = (struct wilc_priv *)pUserVoid;
c5c77ba1 541 dev = priv->dev;
c1ec2c12
GL
542 nic = netdev_priv(dev);
543 wl = nic->wilc;
441dc609 544 pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv;
c5c77ba1
JK
545
546 if (enuConnDisconnEvent == CONN_DISCONN_EVENT_CONN_RESP) {
547 /*Initialization*/
baba7c74 548 u16 u16ConnectStatus;
c5c77ba1
JK
549
550 u16ConnectStatus = pstrConnectInfo->u16ConnectStatus;
551
552 PRINT_D(CFG80211_DBG, " Connection response received = %d\n", u8MacStatus);
553
554 if ((u8MacStatus == MAC_DISCONNECTED) &&
555 (pstrConnectInfo->u16ConnectStatus == SUCCESSFUL_STATUSCODE)) {
556 /* The case here is that our station was waiting for association response frame and has just received it containing status code
557 * = SUCCESSFUL_STATUSCODE, while mac status is MAC_DISCONNECTED (which means something wrong happened) */
558 u16ConnectStatus = WLAN_STATUS_UNSPECIFIED_FAILURE;
559 linux_wlan_set_bssid(priv->dev, NullBssid);
bcf02653 560 eth_zero_addr(u8ConnectedSSID);
c5c77ba1 561
c5c77ba1 562 /*Invalidate u8WLANChannel value on wlan0 disconnect*/
ab16ec0b 563 if (!pstrWFIDrv->p2p_connect)
c5c77ba1 564 u8WLANChannel = INVALID_CHANNEL;
c5c77ba1 565
17aacd43 566 PRINT_ER("Unspecified failure: Connection status %d : MAC status = %d\n", u16ConnectStatus, u8MacStatus);
c5c77ba1
JK
567 }
568
569 if (u16ConnectStatus == WLAN_STATUS_SUCCESS) {
72ed4dc7 570 bool bNeedScanRefresh = false;
4e4467fd 571 u32 i;
c5c77ba1
JK
572
573 PRINT_INFO(CFG80211_DBG, "Connection Successful:: BSSID: %x%x%x%x%x%x\n", pstrConnectInfo->au8bssid[0],
574 pstrConnectInfo->au8bssid[1], pstrConnectInfo->au8bssid[2], pstrConnectInfo->au8bssid[3], pstrConnectInfo->au8bssid[4], pstrConnectInfo->au8bssid[5]);
d00d2ba3 575 memcpy(priv->au8AssociatedBss, pstrConnectInfo->au8bssid, ETH_ALEN);
c5c77ba1 576
c5c77ba1
JK
577
578 for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
1a646e7e 579 if (memcmp(astrLastScannedNtwrksShadow[i].au8bssid,
c5c77ba1
JK
580 pstrConnectInfo->au8bssid, ETH_ALEN) == 0) {
581 unsigned long now = jiffies;
582
583 if (time_after(now,
584 astrLastScannedNtwrksShadow[i].u32TimeRcvdInScanCached + (unsigned long)(nl80211_SCAN_RESULT_EXPIRE - (1 * HZ)))) {
72ed4dc7 585 bNeedScanRefresh = true;
c5c77ba1
JK
586 }
587
588 break;
589 }
590 }
591
5a66bf20 592 if (bNeedScanRefresh) {
c5c77ba1 593 /*Also, refrsh DIRECT- results if */
72ed4dc7 594 refresh_scan(priv, 1, true);
c5c77ba1
JK
595
596 }
597
598 }
599
600
52db7520 601 PRINT_D(CFG80211_DBG, "Association request info elements length = %zu\n", pstrConnectInfo->ReqIEsLen);
c5c77ba1
JK
602
603 PRINT_D(CFG80211_DBG, "Association response info elements length = %d\n", pstrConnectInfo->u16RespIEsLen);
604
605 cfg80211_connect_result(dev, pstrConnectInfo->au8bssid,
606 pstrConnectInfo->pu8ReqIEs, pstrConnectInfo->ReqIEsLen,
607 pstrConnectInfo->pu8RespIEs, pstrConnectInfo->u16RespIEsLen,
608 u16ConnectStatus, GFP_KERNEL); /* TODO: mostafa: u16ConnectStatus to */
609 /* be replaced by pstrConnectInfo->u16ConnectStatus */
610 } else if (enuConnDisconnEvent == CONN_DISCONN_EVENT_DISCONN_NOTIF) {
72ed4dc7 611 g_obtainingIP = false;
c5c77ba1
JK
612 PRINT_ER("Received MAC_DISCONNECTED from firmware with reason %d on dev [%p]\n",
613 pstrDisconnectNotifInfo->u16reason, priv->dev);
614 u8P2Plocalrandom = 0x01;
615 u8P2Precvrandom = 0x00;
72ed4dc7 616 bWilc_ie = false;
bcf02653 617 eth_zero_addr(priv->au8AssociatedBss);
c5c77ba1 618 linux_wlan_set_bssid(priv->dev, NullBssid);
bcf02653 619 eth_zero_addr(u8ConnectedSSID);
c5c77ba1 620
c5c77ba1 621 /*Invalidate u8WLANChannel value on wlan0 disconnect*/
ab16ec0b 622 if (!pstrWFIDrv->p2p_connect)
c5c77ba1 623 u8WLANChannel = INVALID_CHANNEL;
c5c77ba1
JK
624 /*Incase "P2P CLIENT Connected" send deauthentication reason by 3 to force the WPA_SUPPLICANT to directly change
625 * virtual interface to station*/
c1ec2c12 626 if ((pstrWFIDrv->IFC_UP) && (dev == wl->vif[1].ndev)) {
c5c77ba1
JK
627 pstrDisconnectNotifInfo->u16reason = 3;
628 }
c5c77ba1
JK
629 /*Incase "P2P CLIENT during connection(not connected)" send deauthentication reason by 1 to force the WPA_SUPPLICANT
630 * to scan again and retry the connection*/
c1ec2c12 631 else if ((!pstrWFIDrv->IFC_UP) && (dev == wl->vif[1].ndev)) {
c5c77ba1
JK
632 pstrDisconnectNotifInfo->u16reason = 1;
633 }
634 cfg80211_disconnected(dev, pstrDisconnectNotifInfo->u16reason, pstrDisconnectNotifInfo->ie,
e26bb71d
SM
635 pstrDisconnectNotifInfo->ie_len, false,
636 GFP_KERNEL);
c5c77ba1
JK
637
638 }
639
640}
641
642
643/**
80785a9a 644 * @brief set_channel
c5c77ba1
JK
645 * @details Set channel for a given wireless interface. Some devices
646 * may support multi-channel operation (by channel hopping) so cfg80211
647 * doesn't verify much. Note, however, that the passed netdev may be
648 * %NULL as well if the user requested changing the channel for the
649 * device itself, or for a monitor interface.
650 * @param[in]
651 * @return int : Return 0 on Success
652 * @author mdaftedar
653 * @date 01 MAR 2012
654 * @version 1.0
655 */
80785a9a
CL
656static int set_channel(struct wiphy *wiphy,
657 struct cfg80211_chan_def *chandef)
c5c77ba1 658{
4e4467fd 659 u32 channelnum = 0;
2726887c 660 struct wilc_priv *priv;
dd739ea5 661 int result = 0;
8dfaafd6 662
c5c77ba1
JK
663 priv = wiphy_priv(wiphy);
664
c5c77ba1
JK
665 channelnum = ieee80211_frequency_to_channel(chandef->chan->center_freq);
666 PRINT_D(CFG80211_DBG, "Setting channel %d with frequency %d\n", channelnum, chandef->chan->center_freq);
c5c77ba1 667
866a2c24 668 curr_channel = channelnum;
dd739ea5 669 result = host_int_set_mac_chnl_num(priv->hWILCWFIDrv, channelnum);
c5c77ba1 670
dd739ea5 671 if (result != 0)
c5c77ba1
JK
672 PRINT_ER("Error in setting channel %d\n", channelnum);
673
dd739ea5 674 return result;
c5c77ba1
JK
675}
676
677/**
0e30d06d 678 * @brief scan
c5c77ba1
JK
679 * @details Request to do a scan. If returning zero, the scan request is given
680 * the driver, and will be valid until passed to cfg80211_scan_done().
681 * For scan results, call cfg80211_inform_bss(); you can call this outside
682 * the scan/scan_done bracket too.
683 * @param[in]
684 * @return int : Return 0 on Success
685 * @author mabubakr
686 * @date 01 MAR 2012
687 * @version 1.0
688 */
689
0e30d06d 690static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
c5c77ba1 691{
2726887c 692 struct wilc_priv *priv;
4e4467fd 693 u32 i;
e6e12661 694 s32 s32Error = 0;
63d03e47 695 u8 au8ScanChanList[MAX_NUM_SCANNED_NETWORKS];
607db447 696 struct hidden_network strHiddenNetwork;
c5c77ba1
JK
697
698 priv = wiphy_priv(wiphy);
699
c5c77ba1
JK
700 priv->pstrScanReq = request;
701
702 priv->u32RcvdChCount = 0;
703
218dc407 704 host_int_set_wfi_drv_handler(priv->hWILCWFIDrv);
c5c77ba1
JK
705
706
707 reset_shadow_found(priv);
708
72ed4dc7 709 priv->bCfgScanning = true;
c5c77ba1
JK
710 if (request->n_channels <= MAX_NUM_SCANNED_NETWORKS) { /* TODO: mostafa: to be replaced by */
711 /* max_scan_ssids */
712 for (i = 0; i < request->n_channels; i++) {
63d03e47 713 au8ScanChanList[i] = (u8)ieee80211_frequency_to_channel(request->channels[i]->center_freq);
c5c77ba1
JK
714 PRINT_INFO(CFG80211_DBG, "ScanChannel List[%d] = %d,", i, au8ScanChanList[i]);
715 }
716
717 PRINT_D(CFG80211_DBG, "Requested num of scan channel %d\n", request->n_channels);
52db7520 718 PRINT_D(CFG80211_DBG, "Scan Request IE len = %zu\n", request->ie_len);
c5c77ba1
JK
719
720 PRINT_D(CFG80211_DBG, "Number of SSIDs %d\n", request->n_ssids);
721
722 if (request->n_ssids >= 1) {
723
724
607db447 725 strHiddenNetwork.pstrHiddenNetworkInfo = kmalloc(request->n_ssids * sizeof(struct hidden_network), GFP_KERNEL);
c5c77ba1
JK
726 strHiddenNetwork.u8ssidnum = request->n_ssids;
727
728
c5c77ba1
JK
729 for (i = 0; i < request->n_ssids; i++) {
730
731 if (request->ssids[i].ssid != NULL && request->ssids[i].ssid_len != 0) {
f3052587 732 strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid = kmalloc(request->ssids[i].ssid_len, GFP_KERNEL);
d00d2ba3 733 memcpy(strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid, request->ssids[i].ssid, request->ssids[i].ssid_len);
c5c77ba1
JK
734 strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen = request->ssids[i].ssid_len;
735 } else {
17aacd43 736 PRINT_D(CFG80211_DBG, "Received one NULL SSID\n");
c5c77ba1
JK
737 strHiddenNetwork.u8ssidnum -= 1;
738 }
739 }
17aacd43 740 PRINT_D(CFG80211_DBG, "Trigger Scan Request\n");
c5c77ba1
JK
741 s32Error = host_int_scan(priv->hWILCWFIDrv, USER_SCAN, ACTIVE_SCAN,
742 au8ScanChanList, request->n_channels,
63d03e47 743 (const u8 *)request->ie, request->ie_len,
c5c77ba1
JK
744 CfgScanResult, (void *)priv, &strHiddenNetwork);
745 } else {
17aacd43 746 PRINT_D(CFG80211_DBG, "Trigger Scan Request\n");
c5c77ba1
JK
747 s32Error = host_int_scan(priv->hWILCWFIDrv, USER_SCAN, ACTIVE_SCAN,
748 au8ScanChanList, request->n_channels,
63d03e47 749 (const u8 *)request->ie, request->ie_len,
c5c77ba1
JK
750 CfgScanResult, (void *)priv, NULL);
751 }
752
753 } else {
754 PRINT_ER("Requested num of scanned channels is greater than the max, supported"
17aacd43 755 " channels\n");
c5c77ba1
JK
756 }
757
e6e12661 758 if (s32Error != 0) {
c5c77ba1
JK
759 s32Error = -EBUSY;
760 PRINT_WRN(CFG80211_DBG, "Device is busy: Error(%d)\n", s32Error);
761 }
762
763 return s32Error;
764}
765
766/**
4ffbcdb6 767 * @brief connect
c5c77ba1
JK
768 * @details Connect to the ESS with the specified parameters. When connected,
769 * call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS.
770 * If the connection fails for some reason, call cfg80211_connect_result()
771 * with the status from the AP.
772 * @param[in]
773 * @return int : Return 0 on Success
774 * @author mabubakr
775 * @date 01 MAR 2012
776 * @version 1.0
777 */
4ffbcdb6
CL
778static int connect(struct wiphy *wiphy, struct net_device *dev,
779 struct cfg80211_connect_params *sme)
c5c77ba1 780{
e6e12661 781 s32 s32Error = 0;
4e4467fd 782 u32 i;
63d03e47 783 u8 u8security = NO_ENCRYPT;
841dfc42 784 enum AUTHTYPE tenuAuth_type = ANY;
576917ad
DL
785 char *pcgroup_encrypt_val = NULL;
786 char *pccipher_group = NULL;
787 char *pcwpa_version = NULL;
c5c77ba1 788
2726887c 789 struct wilc_priv *priv;
441dc609 790 struct host_if_drv *pstrWFIDrv;
c5c77ba1
JK
791 tstrNetworkInfo *pstrNetworkInfo = NULL;
792
793
794 connecting = 1;
795 priv = wiphy_priv(wiphy);
441dc609 796 pstrWFIDrv = (struct host_if_drv *)(priv->hWILCWFIDrv);
c5c77ba1 797
218dc407 798 host_int_set_wfi_drv_handler(priv->hWILCWFIDrv);
c5c77ba1 799
8a14330f 800 PRINT_D(CFG80211_DBG, "Connecting to SSID [%s] on netdev [%p] host if [%p]\n", sme->ssid, dev, priv->hWILCWFIDrv);
3f882895 801 if (!(strncmp(sme->ssid, "DIRECT-", 7))) {
c5c77ba1 802 PRINT_D(CFG80211_DBG, "Connected to Direct network,OBSS disabled\n");
ab16ec0b
LK
803 pstrWFIDrv->p2p_connect = 1;
804 } else {
805 pstrWFIDrv->p2p_connect = 0;
806 }
17aacd43 807 PRINT_INFO(CFG80211_DBG, "Required SSID = %s\n , AuthType = %d\n", sme->ssid, sme->auth_type);
c5c77ba1
JK
808
809 for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
810 if ((sme->ssid_len == astrLastScannedNtwrksShadow[i].u8SsidLen) &&
1a646e7e 811 memcmp(astrLastScannedNtwrksShadow[i].au8ssid,
c5c77ba1
JK
812 sme->ssid,
813 sme->ssid_len) == 0) {
814 PRINT_INFO(CFG80211_DBG, "Network with required SSID is found %s\n", sme->ssid);
815 if (sme->bssid == NULL) {
816 /* BSSID is not passed from the user, so decision of matching
817 * is done by SSID only */
818 PRINT_INFO(CFG80211_DBG, "BSSID is not passed from the user\n");
819 break;
820 } else {
821 /* BSSID is also passed from the user, so decision of matching
822 * should consider also this passed BSSID */
1a646e7e 823 if (memcmp(astrLastScannedNtwrksShadow[i].au8bssid,
c5c77ba1
JK
824 sme->bssid,
825 ETH_ALEN) == 0) {
826 PRINT_INFO(CFG80211_DBG, "BSSID is passed from the user and matched\n");
827 break;
828 }
829 }
830 }
831 }
832
833 if (i < u32LastScannedNtwrksCountShadow) {
834 PRINT_D(CFG80211_DBG, "Required bss is in scan results\n");
835
836 pstrNetworkInfo = &(astrLastScannedNtwrksShadow[i]);
837
838 PRINT_INFO(CFG80211_DBG, "network BSSID to be associated: %x%x%x%x%x%x\n",
839 pstrNetworkInfo->au8bssid[0], pstrNetworkInfo->au8bssid[1],
840 pstrNetworkInfo->au8bssid[2], pstrNetworkInfo->au8bssid[3],
841 pstrNetworkInfo->au8bssid[4], pstrNetworkInfo->au8bssid[5]);
842 } else {
843 s32Error = -ENOENT;
844 if (u32LastScannedNtwrksCountShadow == 0)
845 PRINT_D(CFG80211_DBG, "No Scan results yet\n");
846 else
847 PRINT_D(CFG80211_DBG, "Required bss not in scan results: Error(%d)\n", s32Error);
848
849 goto done;
850 }
851
852 priv->WILC_WFI_wep_default = 0;
2cc46837
CL
853 memset(priv->WILC_WFI_wep_key, 0, sizeof(priv->WILC_WFI_wep_key));
854 memset(priv->WILC_WFI_wep_key_len, 0, sizeof(priv->WILC_WFI_wep_key_len));
c5c77ba1
JK
855
856 PRINT_INFO(CFG80211_DBG, "sme->crypto.wpa_versions=%x\n", sme->crypto.wpa_versions);
857 PRINT_INFO(CFG80211_DBG, "sme->crypto.cipher_group=%x\n", sme->crypto.cipher_group);
858
859 PRINT_INFO(CFG80211_DBG, "sme->crypto.n_ciphers_pairwise=%d\n", sme->crypto.n_ciphers_pairwise);
860
861 if (INFO) {
862 for (i = 0; i < sme->crypto.n_ciphers_pairwise; i++)
863 PRINT_D(CORECONFIG_DBG, "sme->crypto.ciphers_pairwise[%d]=%x\n", i, sme->crypto.ciphers_pairwise[i]);
864 }
865
866 if (sme->crypto.cipher_group != NO_ENCRYPT) {
867 /* To determine the u8security value, first we check the group cipher suite then {in case of WPA or WPA2}
868 * we will add to it the pairwise cipher suite(s) */
869 pcwpa_version = "Default";
870 PRINT_D(CORECONFIG_DBG, ">> sme->crypto.wpa_versions: %x\n", sme->crypto.wpa_versions);
c5c77ba1 871 if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) {
c5c77ba1
JK
872 u8security = ENCRYPT_ENABLED | WEP;
873 pcgroup_encrypt_val = "WEP40";
874 pccipher_group = "WLAN_CIPHER_SUITE_WEP40";
875 PRINT_INFO(CFG80211_DBG, "WEP Default Key Idx = %d\n", sme->key_idx);
876
877 if (INFO) {
878 for (i = 0; i < sme->key_len; i++)
879 PRINT_D(CORECONFIG_DBG, "WEP Key Value[%d] = %d\n", i, sme->key[i]);
880 }
881 priv->WILC_WFI_wep_default = sme->key_idx;
882 priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len;
d00d2ba3 883 memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len);
c5c77ba1 884
c5c77ba1 885 g_key_wep_params.key_len = sme->key_len;
f3052587 886 g_key_wep_params.key = kmalloc(sme->key_len, GFP_KERNEL);
c5c77ba1
JK
887 memcpy(g_key_wep_params.key, sme->key, sme->key_len);
888 g_key_wep_params.key_idx = sme->key_idx;
72ed4dc7 889 g_wep_keys_saved = true;
c5c77ba1 890
df8b4830 891 host_int_set_wep_default_key(priv->hWILCWFIDrv, sme->key_idx);
c5c77ba1
JK
892 host_int_add_wep_key_bss_sta(priv->hWILCWFIDrv, sme->key, sme->key_len, sme->key_idx);
893 } else if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104) {
c5c77ba1
JK
894 u8security = ENCRYPT_ENABLED | WEP | WEP_EXTENDED;
895 pcgroup_encrypt_val = "WEP104";
896 pccipher_group = "WLAN_CIPHER_SUITE_WEP104";
897
898 priv->WILC_WFI_wep_default = sme->key_idx;
899 priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len;
d00d2ba3 900 memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len);
c5c77ba1 901
c5c77ba1 902 g_key_wep_params.key_len = sme->key_len;
f3052587 903 g_key_wep_params.key = kmalloc(sme->key_len, GFP_KERNEL);
c5c77ba1
JK
904 memcpy(g_key_wep_params.key, sme->key, sme->key_len);
905 g_key_wep_params.key_idx = sme->key_idx;
72ed4dc7 906 g_wep_keys_saved = true;
c5c77ba1 907
df8b4830 908 host_int_set_wep_default_key(priv->hWILCWFIDrv, sme->key_idx);
c5c77ba1
JK
909 host_int_add_wep_key_bss_sta(priv->hWILCWFIDrv, sme->key, sme->key_len, sme->key_idx);
910 } else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) {
c5c77ba1 911 if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_TKIP) {
c5c77ba1
JK
912 u8security = ENCRYPT_ENABLED | WPA2 | TKIP;
913 pcgroup_encrypt_val = "WPA2_TKIP";
914 pccipher_group = "TKIP";
915 } else { /* TODO: mostafa: here we assume that any other encryption type is AES */
916 /* tenuSecurity_t = WPA2_AES; */
917 u8security = ENCRYPT_ENABLED | WPA2 | AES;
918 pcgroup_encrypt_val = "WPA2_AES";
919 pccipher_group = "AES";
920 }
921 pcwpa_version = "WPA_VERSION_2";
922 } else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) {
923 if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_TKIP) {
c5c77ba1
JK
924 u8security = ENCRYPT_ENABLED | WPA | TKIP;
925 pcgroup_encrypt_val = "WPA_TKIP";
926 pccipher_group = "TKIP";
927 } else { /* TODO: mostafa: here we assume that any other encryption type is AES */
928 /* tenuSecurity_t = WPA_AES; */
929 u8security = ENCRYPT_ENABLED | WPA | AES;
930 pcgroup_encrypt_val = "WPA_AES";
931 pccipher_group = "AES";
932
933 }
934 pcwpa_version = "WPA_VERSION_1";
935
c5c77ba1
JK
936 } else {
937 s32Error = -ENOTSUPP;
938 PRINT_ER("Not supported cipher: Error(%d)\n", s32Error);
939
940 goto done;
941 }
942
943 }
944
945 /* After we set the u8security value from checking the group cipher suite, {in case of WPA or WPA2} we will
946 * add to it the pairwise cipher suite(s) */
947 if ((sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
948 || (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)) {
949 for (i = 0; i < sme->crypto.n_ciphers_pairwise; i++) {
950 if (sme->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP) {
951 u8security = u8security | TKIP;
952 } else { /* TODO: mostafa: here we assume that any other encryption type is AES */
953 u8security = u8security | AES;
954 }
955 }
956 }
957
958 PRINT_D(CFG80211_DBG, "Adding key with cipher group = %x\n", sme->crypto.cipher_group);
959
960 PRINT_D(CFG80211_DBG, "Authentication Type = %d\n", sme->auth_type);
961 switch (sme->auth_type) {
962 case NL80211_AUTHTYPE_OPEN_SYSTEM:
963 PRINT_D(CFG80211_DBG, "In OPEN SYSTEM\n");
964 tenuAuth_type = OPEN_SYSTEM;
965 break;
966
967 case NL80211_AUTHTYPE_SHARED_KEY:
968 tenuAuth_type = SHARED_KEY;
969 PRINT_D(CFG80211_DBG, "In SHARED KEY\n");
970 break;
971
972 default:
973 PRINT_D(CFG80211_DBG, "Automatic Authentation type = %d\n", sme->auth_type);
974 }
975
976
977 /* ai: key_mgmt: enterprise case */
978 if (sme->crypto.n_akm_suites) {
979 switch (sme->crypto.akm_suites[0]) {
980 case WLAN_AKM_SUITE_8021X:
981 tenuAuth_type = IEEE8021;
982 break;
983
984 default:
985 break;
986 }
987 }
988
989
990 PRINT_INFO(CFG80211_DBG, "Required Channel = %d\n", pstrNetworkInfo->u8channel);
991
992 PRINT_INFO(CFG80211_DBG, "Group encryption value = %s\n Cipher Group = %s\n WPA version = %s\n",
993 pcgroup_encrypt_val, pccipher_group, pcwpa_version);
994
866a2c24 995 curr_channel = pstrNetworkInfo->u8channel;
c5c77ba1 996
ab16ec0b 997 if (!pstrWFIDrv->p2p_connect)
c5c77ba1 998 u8WLANChannel = pstrNetworkInfo->u8channel;
c5c77ba1
JK
999
1000 linux_wlan_set_bssid(dev, pstrNetworkInfo->au8bssid);
1001
1002 s32Error = host_int_set_join_req(priv->hWILCWFIDrv, pstrNetworkInfo->au8bssid, sme->ssid,
1003 sme->ssid_len, sme->ie, sme->ie_len,
1004 CfgConnectResult, (void *)priv, u8security,
1005 tenuAuth_type, pstrNetworkInfo->u8channel,
1006 pstrNetworkInfo->pJoinParams);
e6e12661 1007 if (s32Error != 0) {
17aacd43 1008 PRINT_ER("host_int_set_join_req(): Error(%d)\n", s32Error);
c5c77ba1
JK
1009 s32Error = -ENOENT;
1010 goto done;
1011 }
1012
1013done:
1014
1015 return s32Error;
1016}
1017
1018
1019/**
b027cde9 1020 * @brief disconnect
c5c77ba1
JK
1021 * @details Disconnect from the BSS/ESS.
1022 * @param[in]
1023 * @return int : Return 0 on Success
1024 * @author mdaftedar
1025 * @date 01 MAR 2012
1026 * @version 1.0
1027 */
b027cde9 1028static int disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code)
c5c77ba1 1029{
e6e12661 1030 s32 s32Error = 0;
2726887c 1031 struct wilc_priv *priv;
441dc609 1032 struct host_if_drv *pstrWFIDrv;
51e825f7 1033 u8 NullBssid[ETH_ALEN] = {0};
8dfaafd6 1034
c5c77ba1
JK
1035 connecting = 0;
1036 priv = wiphy_priv(wiphy);
1037
c5c77ba1 1038 /*Invalidate u8WLANChannel value on wlan0 disconnect*/
441dc609 1039 pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv;
ab16ec0b 1040 if (!pstrWFIDrv->p2p_connect)
c5c77ba1 1041 u8WLANChannel = INVALID_CHANNEL;
c5c77ba1
JK
1042 linux_wlan_set_bssid(priv->dev, NullBssid);
1043
1044 PRINT_D(CFG80211_DBG, "Disconnecting with reason code(%d)\n", reason_code);
1045
1046 u8P2Plocalrandom = 0x01;
1047 u8P2Precvrandom = 0x00;
72ed4dc7 1048 bWilc_ie = false;
1229b1ab 1049 pstrWFIDrv->p2p_timeout = 0;
c5c77ba1
JK
1050
1051 s32Error = host_int_disconnect(priv->hWILCWFIDrv, reason_code);
e6e12661 1052 if (s32Error != 0) {
c5c77ba1
JK
1053 PRINT_ER("Error in disconnecting: Error(%d)\n", s32Error);
1054 s32Error = -EINVAL;
1055 }
1056
1057 return s32Error;
1058}
1059
1060/**
953d417a 1061 * @brief add_key
c5c77ba1
JK
1062 * @details Add a key with the given parameters. @mac_addr will be %NULL
1063 * when adding a group key.
1064 * @param[in] key : key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key, 8-byte Rx Mic Key
1065 * @return int : Return 0 on Success
1066 * @author mdaftedar
1067 * @date 01 MAR 2012
1068 * @version 1.0
1069 */
953d417a
CL
1070static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
1071 bool pairwise,
1072 const u8 *mac_addr, struct key_params *params)
c5c77ba1
JK
1073
1074{
e6e12661 1075 s32 s32Error = 0, KeyLen = params->key_len;
4e4467fd 1076 u32 i;
2726887c 1077 struct wilc_priv *priv;
057d1e97
AB
1078 const u8 *pu8RxMic = NULL;
1079 const u8 *pu8TxMic = NULL;
63d03e47 1080 u8 u8mode = NO_ENCRYPT;
63d03e47
GKH
1081 u8 u8gmode = NO_ENCRYPT;
1082 u8 u8pmode = NO_ENCRYPT;
841dfc42 1083 enum AUTHTYPE tenuAuth_type = ANY;
76469200
GL
1084 struct wilc *wl;
1085 perInterface_wlan_t *nic;
c5c77ba1
JK
1086
1087 priv = wiphy_priv(wiphy);
76469200
GL
1088 nic = netdev_priv(netdev);
1089 wl = nic->wilc;
c5c77ba1
JK
1090
1091 PRINT_D(CFG80211_DBG, "Adding key with cipher suite = %x\n", params->cipher);
1092
8a14330f 1093 PRINT_D(CFG80211_DBG, "%p %p %d\n", wiphy, netdev, key_index);
c5c77ba1
JK
1094
1095 PRINT_D(CFG80211_DBG, "key %x %x %x\n", params->key[0],
1096 params->key[1],
1097 params->key[2]);
1098
1099
1100 switch (params->cipher) {
1101 case WLAN_CIPHER_SUITE_WEP40:
1102 case WLAN_CIPHER_SUITE_WEP104:
c5c77ba1
JK
1103 if (priv->wdev->iftype == NL80211_IFTYPE_AP) {
1104
1105 priv->WILC_WFI_wep_default = key_index;
1106 priv->WILC_WFI_wep_key_len[key_index] = params->key_len;
d00d2ba3 1107 memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len);
c5c77ba1
JK
1108
1109 PRINT_D(CFG80211_DBG, "Adding AP WEP Default key Idx = %d\n", key_index);
1110 PRINT_D(CFG80211_DBG, "Adding AP WEP Key len= %d\n", params->key_len);
1111
1112 for (i = 0; i < params->key_len; i++)
1113 PRINT_D(CFG80211_DBG, "WEP AP key val[%d] = %x\n", i, params->key[i]);
1114
1115 tenuAuth_type = OPEN_SYSTEM;
1116
1117 if (params->cipher == WLAN_CIPHER_SUITE_WEP40)
1118 u8mode = ENCRYPT_ENABLED | WEP;
1119 else
1120 u8mode = ENCRYPT_ENABLED | WEP | WEP_EXTENDED;
1121
1122 host_int_add_wep_key_bss_ap(priv->hWILCWFIDrv, params->key, params->key_len, key_index, u8mode, tenuAuth_type);
1123 break;
1124 }
1a646e7e 1125 if (memcmp(params->key, priv->WILC_WFI_wep_key[key_index], params->key_len)) {
c5c77ba1
JK
1126 priv->WILC_WFI_wep_default = key_index;
1127 priv->WILC_WFI_wep_key_len[key_index] = params->key_len;
d00d2ba3 1128 memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len);
c5c77ba1
JK
1129
1130 PRINT_D(CFG80211_DBG, "Adding WEP Default key Idx = %d\n", key_index);
1131 PRINT_D(CFG80211_DBG, "Adding WEP Key length = %d\n", params->key_len);
1132 if (INFO) {
1133 for (i = 0; i < params->key_len; i++)
1134 PRINT_INFO(CFG80211_DBG, "WEP key value[%d] = %d\n", i, params->key[i]);
1135 }
1136 host_int_add_wep_key_bss_sta(priv->hWILCWFIDrv, params->key, params->key_len, key_index);
1137 }
1138
1139 break;
1140
1141 case WLAN_CIPHER_SUITE_TKIP:
1142 case WLAN_CIPHER_SUITE_CCMP:
c5c77ba1
JK
1143 if (priv->wdev->iftype == NL80211_IFTYPE_AP || priv->wdev->iftype == NL80211_IFTYPE_P2P_GO) {
1144
1145 if (priv->wilc_gtk[key_index] == NULL) {
f3052587 1146 priv->wilc_gtk[key_index] = kmalloc(sizeof(struct wilc_wfi_key), GFP_KERNEL);
b1413b60
GKH
1147 priv->wilc_gtk[key_index]->key = NULL;
1148 priv->wilc_gtk[key_index]->seq = NULL;
c5c77ba1
JK
1149
1150 }
1151 if (priv->wilc_ptk[key_index] == NULL) {
f3052587 1152 priv->wilc_ptk[key_index] = kmalloc(sizeof(struct wilc_wfi_key), GFP_KERNEL);
b1413b60
GKH
1153 priv->wilc_ptk[key_index]->key = NULL;
1154 priv->wilc_ptk[key_index]->seq = NULL;
c5c77ba1
JK
1155 }
1156
1157
1158
1913221c 1159 if (!pairwise) {
c5c77ba1
JK
1160 if (params->cipher == WLAN_CIPHER_SUITE_TKIP)
1161 u8gmode = ENCRYPT_ENABLED | WPA | TKIP;
1162 else
1163 u8gmode = ENCRYPT_ENABLED | WPA2 | AES;
1164
1165 priv->wilc_groupkey = u8gmode;
1166
1167 if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
1168
1169 pu8TxMic = params->key + 24;
1170 pu8RxMic = params->key + 16;
1171 KeyLen = params->key_len - 16;
1172 }
1173 /* if there has been previous allocation for the same index through its key, free that memory and allocate again*/
cccfc39e 1174 kfree(priv->wilc_gtk[key_index]->key);
c5c77ba1 1175
f3052587 1176 priv->wilc_gtk[key_index]->key = kmalloc(params->key_len, GFP_KERNEL);
d00d2ba3 1177 memcpy(priv->wilc_gtk[key_index]->key, params->key, params->key_len);
c5c77ba1
JK
1178
1179 /* if there has been previous allocation for the same index through its seq, free that memory and allocate again*/
cccfc39e 1180 kfree(priv->wilc_gtk[key_index]->seq);
c5c77ba1
JK
1181
1182 if ((params->seq_len) > 0) {
f3052587 1183 priv->wilc_gtk[key_index]->seq = kmalloc(params->seq_len, GFP_KERNEL);
d00d2ba3 1184 memcpy(priv->wilc_gtk[key_index]->seq, params->seq, params->seq_len);
c5c77ba1
JK
1185 }
1186
1187 priv->wilc_gtk[key_index]->cipher = params->cipher;
1188 priv->wilc_gtk[key_index]->key_len = params->key_len;
1189 priv->wilc_gtk[key_index]->seq_len = params->seq_len;
1190
1191 if (INFO) {
1192 for (i = 0; i < params->key_len; i++)
1193 PRINT_INFO(CFG80211_DBG, "Adding group key value[%d] = %x\n", i, params->key[i]);
1194 for (i = 0; i < params->seq_len; i++)
1195 PRINT_INFO(CFG80211_DBG, "Adding group seq value[%d] = %x\n", i, params->seq[i]);
1196 }
1197
1198
1199 host_int_add_rx_gtk(priv->hWILCWFIDrv, params->key, KeyLen,
1200 key_index, params->seq_len, params->seq, pu8RxMic, pu8TxMic, AP_MODE, u8gmode);
1201
1202 } else {
1203 PRINT_INFO(CFG80211_DBG, "STA Address: %x%x%x%x%x\n", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4]);
1204
1205 if (params->cipher == WLAN_CIPHER_SUITE_TKIP)
1206 u8pmode = ENCRYPT_ENABLED | WPA | TKIP;
1207 else
1208 u8pmode = priv->wilc_groupkey | AES;
1209
1210
1211 if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
1212
1213 pu8TxMic = params->key + 24;
1214 pu8RxMic = params->key + 16;
1215 KeyLen = params->key_len - 16;
1216 }
1217
cccfc39e 1218 kfree(priv->wilc_ptk[key_index]->key);
c5c77ba1 1219
f3052587 1220 priv->wilc_ptk[key_index]->key = kmalloc(params->key_len, GFP_KERNEL);
c5c77ba1 1221
cccfc39e 1222 kfree(priv->wilc_ptk[key_index]->seq);
c5c77ba1
JK
1223
1224 if ((params->seq_len) > 0)
f3052587 1225 priv->wilc_ptk[key_index]->seq = kmalloc(params->seq_len, GFP_KERNEL);
c5c77ba1
JK
1226
1227 if (INFO) {
1228 for (i = 0; i < params->key_len; i++)
1229 PRINT_INFO(CFG80211_DBG, "Adding pairwise key value[%d] = %x\n", i, params->key[i]);
1230
1231 for (i = 0; i < params->seq_len; i++)
1232 PRINT_INFO(CFG80211_DBG, "Adding group seq value[%d] = %x\n", i, params->seq[i]);
1233 }
1234
d00d2ba3 1235 memcpy(priv->wilc_ptk[key_index]->key, params->key, params->key_len);
c5c77ba1
JK
1236
1237 if ((params->seq_len) > 0)
d00d2ba3 1238 memcpy(priv->wilc_ptk[key_index]->seq, params->seq, params->seq_len);
c5c77ba1
JK
1239
1240 priv->wilc_ptk[key_index]->cipher = params->cipher;
1241 priv->wilc_ptk[key_index]->key_len = params->key_len;
1242 priv->wilc_ptk[key_index]->seq_len = params->seq_len;
1243
1244 host_int_add_ptk(priv->hWILCWFIDrv, params->key, KeyLen, mac_addr,
1245 pu8RxMic, pu8TxMic, AP_MODE, u8pmode, key_index);
1246 }
1247 break;
1248 }
c5c77ba1
JK
1249
1250 {
1251 u8mode = 0;
1913221c 1252 if (!pairwise) {
c5c77ba1
JK
1253 if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
1254 /* swap the tx mic by rx mic */
1255 pu8RxMic = params->key + 24;
1256 pu8TxMic = params->key + 16;
1257 KeyLen = params->key_len - 16;
1258 }
1259
c5c77ba1 1260 /*save keys only on interface 0 (wifi interface)*/
76469200 1261 if (!g_gtk_keys_saved && netdev == wl->vif[0].ndev) {
c5c77ba1 1262 g_add_gtk_key_params.key_idx = key_index;
c5c77ba1 1263 g_add_gtk_key_params.pairwise = pairwise;
c5c77ba1
JK
1264 if (!mac_addr) {
1265 g_add_gtk_key_params.mac_addr = NULL;
1266 } else {
f3052587 1267 g_add_gtk_key_params.mac_addr = kmalloc(ETH_ALEN, GFP_KERNEL);
c5c77ba1
JK
1268 memcpy(g_add_gtk_key_params.mac_addr, mac_addr, ETH_ALEN);
1269 }
1270 g_key_gtk_params.key_len = params->key_len;
1271 g_key_gtk_params.seq_len = params->seq_len;
f3052587 1272 g_key_gtk_params.key = kmalloc(params->key_len, GFP_KERNEL);
c5c77ba1
JK
1273 memcpy(g_key_gtk_params.key, params->key, params->key_len);
1274 if (params->seq_len > 0) {
f3052587 1275 g_key_gtk_params.seq = kmalloc(params->seq_len, GFP_KERNEL);
c5c77ba1
JK
1276 memcpy(g_key_gtk_params.seq, params->seq, params->seq_len);
1277 }
1278 g_key_gtk_params.cipher = params->cipher;
1279
1280 PRINT_D(CFG80211_DBG, "key %x %x %x\n", g_key_gtk_params.key[0],
1281 g_key_gtk_params.key[1],
1282 g_key_gtk_params.key[2]);
72ed4dc7 1283 g_gtk_keys_saved = true;
c5c77ba1
JK
1284 }
1285
1286 host_int_add_rx_gtk(priv->hWILCWFIDrv, params->key, KeyLen,
1287 key_index, params->seq_len, params->seq, pu8RxMic, pu8TxMic, STATION_MODE, u8mode);
c5c77ba1
JK
1288 } else {
1289 if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
1290 /* swap the tx mic by rx mic */
1291 pu8RxMic = params->key + 24;
1292 pu8TxMic = params->key + 16;
1293 KeyLen = params->key_len - 16;
1294 }
1295
c5c77ba1 1296 /*save keys only on interface 0 (wifi interface)*/
76469200 1297 if (!g_ptk_keys_saved && netdev == wl->vif[0].ndev) {
c5c77ba1 1298 g_add_ptk_key_params.key_idx = key_index;
c5c77ba1 1299 g_add_ptk_key_params.pairwise = pairwise;
c5c77ba1
JK
1300 if (!mac_addr) {
1301 g_add_ptk_key_params.mac_addr = NULL;
1302 } else {
f3052587 1303 g_add_ptk_key_params.mac_addr = kmalloc(ETH_ALEN, GFP_KERNEL);
c5c77ba1
JK
1304 memcpy(g_add_ptk_key_params.mac_addr, mac_addr, ETH_ALEN);
1305 }
1306 g_key_ptk_params.key_len = params->key_len;
1307 g_key_ptk_params.seq_len = params->seq_len;
f3052587 1308 g_key_ptk_params.key = kmalloc(params->key_len, GFP_KERNEL);
c5c77ba1
JK
1309 memcpy(g_key_ptk_params.key, params->key, params->key_len);
1310 if (params->seq_len > 0) {
f3052587 1311 g_key_ptk_params.seq = kmalloc(params->seq_len, GFP_KERNEL);
c5c77ba1
JK
1312 memcpy(g_key_ptk_params.seq, params->seq, params->seq_len);
1313 }
1314 g_key_ptk_params.cipher = params->cipher;
1315
1316 PRINT_D(CFG80211_DBG, "key %x %x %x\n", g_key_ptk_params.key[0],
1317 g_key_ptk_params.key[1],
1318 g_key_ptk_params.key[2]);
72ed4dc7 1319 g_ptk_keys_saved = true;
c5c77ba1
JK
1320 }
1321
1322 host_int_add_ptk(priv->hWILCWFIDrv, params->key, KeyLen, mac_addr,
1323 pu8RxMic, pu8TxMic, STATION_MODE, u8mode, key_index);
1324 PRINT_D(CFG80211_DBG, "Adding pairwise key\n");
1325 if (INFO) {
1326 for (i = 0; i < params->key_len; i++)
1327 PRINT_INFO(CFG80211_DBG, "Adding pairwise key value[%d] = %d\n", i, params->key[i]);
1328 }
1329 }
1330 }
1331 break;
1332
1333 default:
1334 PRINT_ER("Not supported cipher: Error(%d)\n", s32Error);
1335 s32Error = -ENOTSUPP;
1336
1337 }
1338
1339 return s32Error;
1340}
1341
1342/**
3044ba7e 1343 * @brief del_key
c5c77ba1
JK
1344 * @details Remove a key given the @mac_addr (%NULL for a group key)
1345 * and @key_index, return -ENOENT if the key doesn't exist.
1346 * @param[in]
1347 * @return int : Return 0 on Success
1348 * @author mdaftedar
1349 * @date 01 MAR 2012
1350 * @version 1.0
1351 */
3044ba7e
CL
1352static int del_key(struct wiphy *wiphy, struct net_device *netdev,
1353 u8 key_index,
1354 bool pairwise,
1355 const u8 *mac_addr)
c5c77ba1 1356{
2726887c 1357 struct wilc_priv *priv;
692e2ace
GL
1358 struct wilc *wl;
1359 perInterface_wlan_t *nic;
c5c77ba1
JK
1360
1361 priv = wiphy_priv(wiphy);
692e2ace
GL
1362 nic = netdev_priv(netdev);
1363 wl = nic->wilc;
c5c77ba1 1364
c5c77ba1 1365 /*delete saved keys, if any*/
692e2ace 1366 if (netdev == wl->vif[0].ndev) {
72ed4dc7
DL
1367 g_ptk_keys_saved = false;
1368 g_gtk_keys_saved = false;
1369 g_wep_keys_saved = false;
c5c77ba1
JK
1370
1371 /*Delete saved WEP keys params, if any*/
cccfc39e
SB
1372 kfree(g_key_wep_params.key);
1373 g_key_wep_params.key = NULL;
c5c77ba1
JK
1374
1375 /*freeing memory allocated by "wilc_gtk" and "wilc_ptk" in "WILC_WIFI_ADD_KEY"*/
1376
c5c77ba1
JK
1377 if ((priv->wilc_gtk[key_index]) != NULL) {
1378
cccfc39e
SB
1379 kfree(priv->wilc_gtk[key_index]->key);
1380 priv->wilc_gtk[key_index]->key = NULL;
1381 kfree(priv->wilc_gtk[key_index]->seq);
1382 priv->wilc_gtk[key_index]->seq = NULL;
c5c77ba1 1383
49188af2 1384 kfree(priv->wilc_gtk[key_index]);
c5c77ba1
JK
1385 priv->wilc_gtk[key_index] = NULL;
1386
1387 }
1388
1389 if ((priv->wilc_ptk[key_index]) != NULL) {
1390
cccfc39e
SB
1391 kfree(priv->wilc_ptk[key_index]->key);
1392 priv->wilc_ptk[key_index]->key = NULL;
1393 kfree(priv->wilc_ptk[key_index]->seq);
1394 priv->wilc_ptk[key_index]->seq = NULL;
49188af2 1395 kfree(priv->wilc_ptk[key_index]);
c5c77ba1
JK
1396 priv->wilc_ptk[key_index] = NULL;
1397 }
c5c77ba1
JK
1398
1399 /*Delete saved PTK and GTK keys params, if any*/
cccfc39e
SB
1400 kfree(g_key_ptk_params.key);
1401 g_key_ptk_params.key = NULL;
1402 kfree(g_key_ptk_params.seq);
1403 g_key_ptk_params.seq = NULL;
1404
1405 kfree(g_key_gtk_params.key);
1406 g_key_gtk_params.key = NULL;
1407 kfree(g_key_gtk_params.seq);
1408 g_key_gtk_params.seq = NULL;
c5c77ba1
JK
1409
1410 /*Reset WILC_CHANGING_VIR_IF register to allow adding futrue keys to CE H/W*/
2ad8c47d 1411 set_machw_change_vir_if(netdev, false);
c5c77ba1
JK
1412 }
1413
1414 if (key_index >= 0 && key_index <= 3) {
2cc46837 1415 memset(priv->WILC_WFI_wep_key[key_index], 0, priv->WILC_WFI_wep_key_len[key_index]);
c5c77ba1
JK
1416 priv->WILC_WFI_wep_key_len[key_index] = 0;
1417
1418 PRINT_D(CFG80211_DBG, "Removing WEP key with index = %d\n", key_index);
1419 host_int_remove_wep_key(priv->hWILCWFIDrv, key_index);
1420 } else {
1421 PRINT_D(CFG80211_DBG, "Removing all installed keys\n");
1422 host_int_remove_key(priv->hWILCWFIDrv, mac_addr);
1423 }
1424
aaed3290 1425 return 0;
c5c77ba1
JK
1426}
1427
1428/**
f4893dfc 1429 * @brief get_key
c5c77ba1
JK
1430 * @details Get information about the key with the given parameters.
1431 * @mac_addr will be %NULL when requesting information for a group
1432 * key. All pointers given to the @callback function need not be valid
1433 * after it returns. This function should return an error if it is
1434 * not possible to retrieve the key, -ENOENT if it doesn't exist.
1435 * @param[in]
1436 * @return int : Return 0 on Success
1437 * @author mdaftedar
1438 * @date 01 MAR 2012
1439 * @version 1.0
1440 */
f4893dfc
CL
1441static int get_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
1442 bool pairwise,
1443 const u8 *mac_addr, void *cookie, void (*callback)(void *cookie, struct key_params *))
c5c77ba1 1444{
2726887c 1445 struct wilc_priv *priv;
c5c77ba1 1446 struct key_params key_params;
4e4467fd 1447 u32 i;
8dfaafd6 1448
c5c77ba1
JK
1449 priv = wiphy_priv(wiphy);
1450
1451
3604af50 1452 if (!pairwise) {
c5c77ba1
JK
1453 PRINT_D(CFG80211_DBG, "Getting group key idx: %x\n", key_index);
1454
1455 key_params.key = priv->wilc_gtk[key_index]->key;
1456 key_params.cipher = priv->wilc_gtk[key_index]->cipher;
1457 key_params.key_len = priv->wilc_gtk[key_index]->key_len;
1458 key_params.seq = priv->wilc_gtk[key_index]->seq;
1459 key_params.seq_len = priv->wilc_gtk[key_index]->seq_len;
1460 if (INFO) {
1461 for (i = 0; i < key_params.key_len; i++)
1462 PRINT_INFO(CFG80211_DBG, "Retrieved key value %x\n", key_params.key[i]);
1463 }
1464 } else {
1465 PRINT_D(CFG80211_DBG, "Getting pairwise key\n");
1466
1467 key_params.key = priv->wilc_ptk[key_index]->key;
1468 key_params.cipher = priv->wilc_ptk[key_index]->cipher;
1469 key_params.key_len = priv->wilc_ptk[key_index]->key_len;
1470 key_params.seq = priv->wilc_ptk[key_index]->seq;
1471 key_params.seq_len = priv->wilc_ptk[key_index]->seq_len;
1472 }
1473
1474 callback(cookie, &key_params);
1475
aaed3290 1476 return 0; /* priv->wilc_gtk->key_len ?0 : -ENOENT; */
c5c77ba1
JK
1477}
1478
1479/**
0f5b8ca3 1480 * @brief set_default_key
c5c77ba1
JK
1481 * @details Set the default management frame key on an interface
1482 * @param[in]
1483 * @return int : Return 0 on Success.
1484 * @author mdaftedar
1485 * @date 01 MAR 2012
1486 * @version 1.0
1487 */
0f5b8ca3
CL
1488static int set_default_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
1489 bool unicast, bool multicast)
c5c77ba1 1490{
2726887c 1491 struct wilc_priv *priv;
c5c77ba1
JK
1492
1493
1494 priv = wiphy_priv(wiphy);
1495
17aacd43 1496 PRINT_D(CFG80211_DBG, "Setting default key with idx = %d\n", key_index);
c5c77ba1
JK
1497
1498 if (key_index != priv->WILC_WFI_wep_default) {
1499
df8b4830 1500 host_int_set_wep_default_key(priv->hWILCWFIDrv, key_index);
c5c77ba1
JK
1501 }
1502
aaed3290 1503 return 0;
c5c77ba1
JK
1504}
1505
c5c77ba1 1506/**
f06f562d 1507 * @brief get_station
c5c77ba1
JK
1508 * @details Get station information for the station identified by @mac
1509 * @param[in] NONE
1510 * @return int : Return 0 on Success.
1511 * @author mdaftedar
1512 * @date 01 MAR 2012
1513 * @version 1.0
1514 */
1515
f06f562d
CL
1516static int get_station(struct wiphy *wiphy, struct net_device *dev,
1517 const u8 *mac, struct station_info *sinfo)
c5c77ba1 1518{
2726887c 1519 struct wilc_priv *priv;
c5c77ba1 1520 perInterface_wlan_t *nic;
4e4467fd
CL
1521 u32 i = 0;
1522 u32 associatedsta = 0;
1523 u32 inactive_time = 0;
c5c77ba1
JK
1524 priv = wiphy_priv(wiphy);
1525 nic = netdev_priv(dev);
1526
c5c77ba1
JK
1527 if (nic->iftype == AP_MODE || nic->iftype == GO_MODE) {
1528 PRINT_D(HOSTAPD_DBG, "Getting station parameters\n");
1529
1530 PRINT_INFO(HOSTAPD_DBG, ": %x%x%x%x%x\n", mac[0], mac[1], mac[2], mac[3], mac[4]);
1531
1532 for (i = 0; i < NUM_STA_ASSOCIATED; i++) {
1533
1534 if (!(memcmp(mac, priv->assoc_stainfo.au8Sta_AssociatedBss[i], ETH_ALEN))) {
1535 associatedsta = i;
1536 break;
1537 }
1538
1539 }
1540
1541 if (associatedsta == -1) {
aaed3290
LK
1542 PRINT_ER("Station required is not associated\n");
1543 return -ENOENT;
c5c77ba1
JK
1544 }
1545
c5c77ba1 1546 sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME);
c5c77ba1
JK
1547
1548 host_int_get_inactive_time(priv->hWILCWFIDrv, mac, &(inactive_time));
1549 sinfo->inactive_time = 1000 * inactive_time;
1550 PRINT_D(CFG80211_DBG, "Inactive time %d\n", sinfo->inactive_time);
1551
1552 }
c5c77ba1
JK
1553
1554 if (nic->iftype == STATION_MODE) {
03e7b9c4 1555 struct rf_info strStatistics;
8dfaafd6 1556
c5c77ba1
JK
1557 host_int_get_statistics(priv->hWILCWFIDrv, &strStatistics);
1558
c5c77ba1 1559 sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL) |
6212990a 1560 BIT(NL80211_STA_INFO_RX_PACKETS) |
c5c77ba1
JK
1561 BIT(NL80211_STA_INFO_TX_PACKETS) |
1562 BIT(NL80211_STA_INFO_TX_FAILED) |
1563 BIT(NL80211_STA_INFO_TX_BITRATE);
c5c77ba1 1564
00c8dfcf 1565 sinfo->signal = strStatistics.rssi;
9b99274a 1566 sinfo->rx_packets = strStatistics.rx_cnt;
54160376
LK
1567 sinfo->tx_packets = strStatistics.tx_cnt + strStatistics.tx_fail_cnt;
1568 sinfo->tx_failed = strStatistics.tx_fail_cnt;
5babeecb 1569 sinfo->txrate.legacy = strStatistics.link_speed * 10;
c5c77ba1 1570
5babeecb
LK
1571 if ((strStatistics.link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH) &&
1572 (strStatistics.link_speed != DEFAULT_LINK_SPEED))
b9e04aa6 1573 enable_tcp_ack_filter(true);
5babeecb 1574 else if (strStatistics.link_speed != DEFAULT_LINK_SPEED)
b9e04aa6 1575 enable_tcp_ack_filter(false);
c5c77ba1 1576
c5c77ba1
JK
1577 PRINT_D(CORECONFIG_DBG, "*** stats[%d][%d][%d][%d][%d]\n", sinfo->signal, sinfo->rx_packets, sinfo->tx_packets,
1578 sinfo->tx_failed, sinfo->txrate.legacy);
c5c77ba1 1579 }
aaed3290 1580 return 0;
c5c77ba1
JK
1581}
1582
1583
1584/**
a5f7db6a 1585 * @brief change_bss
c5c77ba1
JK
1586 * @details Modify parameters for a given BSS.
1587 * @param[in]
1588 * -use_cts_prot: Whether to use CTS protection
1589 * (0 = no, 1 = yes, -1 = do not change)
1590 * -use_short_preamble: Whether the use of short preambles is allowed
1591 * (0 = no, 1 = yes, -1 = do not change)
1592 * -use_short_slot_time: Whether the use of short slot time is allowed
1593 * (0 = no, 1 = yes, -1 = do not change)
1594 * -basic_rates: basic rates in IEEE 802.11 format
1595 * (or NULL for no change)
1596 * -basic_rates_len: number of basic rates
1597 * -ap_isolate: do not forward packets between connected stations
1598 * -ht_opmode: HT Operation mode
1599 * (u16 = opmode, -1 = do not change)
1600 * @return int : Return 0 on Success.
1601 * @author mdaftedar
1602 * @date 01 MAR 2012
1603 * @version 1.0
1604 */
a5f7db6a
CL
1605static int change_bss(struct wiphy *wiphy, struct net_device *dev,
1606 struct bss_parameters *params)
c5c77ba1
JK
1607{
1608 PRINT_D(CFG80211_DBG, "Changing Bss parametrs\n");
1609 return 0;
1610}
1611
c5c77ba1 1612/**
a76b63ef 1613 * @brief set_wiphy_params
c5c77ba1
JK
1614 * @details Notify that wiphy parameters have changed;
1615 * @param[in] Changed bitfield (see &enum wiphy_params_flags) describes which values
1616 * have changed.
1617 * @return int : Return 0 on Success
1618 * @author mdaftedar
1619 * @date 01 MAR 2012
1620 * @version 1.0
1621 */
a76b63ef 1622static int set_wiphy_params(struct wiphy *wiphy, u32 changed)
c5c77ba1 1623{
e6e12661 1624 s32 s32Error = 0;
9529650a 1625 struct cfg_param_val pstrCfgParamVal;
2726887c 1626 struct wilc_priv *priv;
c5c77ba1
JK
1627
1628 priv = wiphy_priv(wiphy);
c5c77ba1 1629
87c05b28 1630 pstrCfgParamVal.flag = 0;
17aacd43 1631 PRINT_D(CFG80211_DBG, "Setting Wiphy params\n");
c5c77ba1
JK
1632
1633 if (changed & WIPHY_PARAM_RETRY_SHORT) {
1634 PRINT_D(CFG80211_DBG, "Setting WIPHY_PARAM_RETRY_SHORT %d\n",
1635 priv->dev->ieee80211_ptr->wiphy->retry_short);
87c05b28 1636 pstrCfgParamVal.flag |= RETRY_SHORT;
c5c77ba1
JK
1637 pstrCfgParamVal.short_retry_limit = priv->dev->ieee80211_ptr->wiphy->retry_short;
1638 }
1639 if (changed & WIPHY_PARAM_RETRY_LONG) {
1640
1641 PRINT_D(CFG80211_DBG, "Setting WIPHY_PARAM_RETRY_LONG %d\n", priv->dev->ieee80211_ptr->wiphy->retry_long);
87c05b28 1642 pstrCfgParamVal.flag |= RETRY_LONG;
c5c77ba1
JK
1643 pstrCfgParamVal.long_retry_limit = priv->dev->ieee80211_ptr->wiphy->retry_long;
1644
1645 }
1646 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
1647 PRINT_D(CFG80211_DBG, "Setting WIPHY_PARAM_FRAG_THRESHOLD %d\n", priv->dev->ieee80211_ptr->wiphy->frag_threshold);
87c05b28 1648 pstrCfgParamVal.flag |= FRAG_THRESHOLD;
c5c77ba1
JK
1649 pstrCfgParamVal.frag_threshold = priv->dev->ieee80211_ptr->wiphy->frag_threshold;
1650
1651 }
1652
1653 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
1654 PRINT_D(CFG80211_DBG, "Setting WIPHY_PARAM_RTS_THRESHOLD %d\n", priv->dev->ieee80211_ptr->wiphy->rts_threshold);
1655
87c05b28 1656 pstrCfgParamVal.flag |= RTS_THRESHOLD;
c5c77ba1
JK
1657 pstrCfgParamVal.rts_threshold = priv->dev->ieee80211_ptr->wiphy->rts_threshold;
1658
1659 }
1660
1661 PRINT_D(CFG80211_DBG, "Setting CFG params in the host interface\n");
1662 s32Error = hif_set_cfg(priv->hWILCWFIDrv, &pstrCfgParamVal);
1663 if (s32Error)
1664 PRINT_ER("Error in setting WIPHY PARAMS\n");
1665
1666
1667 return s32Error;
1668}
e5af0561 1669
c5c77ba1 1670/**
4d46657a 1671 * @brief set_pmksa
c5c77ba1
JK
1672 * @details Cache a PMKID for a BSSID. This is mostly useful for fullmac
1673 * devices running firmwares capable of generating the (re) association
1674 * RSN IE. It allows for faster roaming between WPA2 BSSIDs.
1675 * @param[in]
1676 * @return int : Return 0 on Success
1677 * @author mdaftedar
1678 * @date 01 MAR 2012
1679 * @version 1.0
1680 */
4d46657a
CL
1681static int set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1682 struct cfg80211_pmksa *pmksa)
c5c77ba1 1683{
4e4467fd 1684 u32 i;
e6e12661 1685 s32 s32Error = 0;
63d03e47 1686 u8 flag = 0;
c5c77ba1 1687
2726887c 1688 struct wilc_priv *priv = wiphy_priv(wiphy);
c5c77ba1
JK
1689
1690 PRINT_D(CFG80211_DBG, "Setting PMKSA\n");
1691
1692
1693 for (i = 0; i < priv->pmkid_list.numpmkid; i++) {
1a646e7e 1694 if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,
c5c77ba1
JK
1695 ETH_ALEN)) {
1696 /*If bssid already exists and pmkid value needs to reset*/
1697 flag = PMKID_FOUND;
1698 PRINT_D(CFG80211_DBG, "PMKID already exists\n");
1699 break;
1700 }
1701 }
1702 if (i < WILC_MAX_NUM_PMKIDS) {
1703 PRINT_D(CFG80211_DBG, "Setting PMKID in private structure\n");
d00d2ba3 1704 memcpy(priv->pmkid_list.pmkidlist[i].bssid, pmksa->bssid,
c5c77ba1 1705 ETH_ALEN);
d00d2ba3 1706 memcpy(priv->pmkid_list.pmkidlist[i].pmkid, pmksa->pmkid,
c5c77ba1
JK
1707 PMKID_LEN);
1708 if (!(flag == PMKID_FOUND))
1709 priv->pmkid_list.numpmkid++;
1710 } else {
1711 PRINT_ER("Invalid PMKID index\n");
1712 s32Error = -EINVAL;
1713 }
1714
1715 if (!s32Error) {
1716 PRINT_D(CFG80211_DBG, "Setting pmkid in the host interface\n");
1717 s32Error = host_int_set_pmkid_info(priv->hWILCWFIDrv, &priv->pmkid_list);
1718 }
1719 return s32Error;
1720}
1721
1722/**
1ff86d96 1723 * @brief del_pmksa
c5c77ba1
JK
1724 * @details Delete a cached PMKID.
1725 * @param[in]
1726 * @return int : Return 0 on Success
1727 * @author mdaftedar
1728 * @date 01 MAR 2012
1729 * @version 1.0
1730 */
1ff86d96
CL
1731static int del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1732 struct cfg80211_pmksa *pmksa)
c5c77ba1
JK
1733{
1734
4e4467fd 1735 u32 i;
e6e12661 1736 s32 s32Error = 0;
c5c77ba1 1737
2726887c 1738 struct wilc_priv *priv = wiphy_priv(wiphy);
c5c77ba1
JK
1739
1740 PRINT_D(CFG80211_DBG, "Deleting PMKSA keys\n");
1741
1742 for (i = 0; i < priv->pmkid_list.numpmkid; i++) {
1a646e7e 1743 if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,
c5c77ba1
JK
1744 ETH_ALEN)) {
1745 /*If bssid is found, reset the values*/
1746 PRINT_D(CFG80211_DBG, "Reseting PMKID values\n");
cd1e6cb4 1747 memset(&priv->pmkid_list.pmkidlist[i], 0, sizeof(struct host_if_pmkid));
c5c77ba1
JK
1748 break;
1749 }
1750 }
1751
1752 if (i < priv->pmkid_list.numpmkid && priv->pmkid_list.numpmkid > 0) {
1753 for (; i < (priv->pmkid_list.numpmkid - 1); i++) {
d00d2ba3 1754 memcpy(priv->pmkid_list.pmkidlist[i].bssid,
c5c77ba1
JK
1755 priv->pmkid_list.pmkidlist[i + 1].bssid,
1756 ETH_ALEN);
d00d2ba3 1757 memcpy(priv->pmkid_list.pmkidlist[i].pmkid,
c5c77ba1
JK
1758 priv->pmkid_list.pmkidlist[i].pmkid,
1759 PMKID_LEN);
1760 }
1761 priv->pmkid_list.numpmkid--;
1762 } else {
1763 s32Error = -EINVAL;
1764 }
1765
1766 return s32Error;
1767}
1768
1769/**
b33c39b1 1770 * @brief flush_pmksa
c5c77ba1
JK
1771 * @details Flush all cached PMKIDs.
1772 * @param[in]
1773 * @return int : Return 0 on Success
1774 * @author mdaftedar
1775 * @date 01 MAR 2012
1776 * @version 1.0
1777 */
b33c39b1 1778static int flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
c5c77ba1 1779{
2726887c 1780 struct wilc_priv *priv = wiphy_priv(wiphy);
c5c77ba1
JK
1781
1782 PRINT_D(CFG80211_DBG, "Flushing PMKID key values\n");
1783
1784 /*Get cashed Pmkids and set all with zeros*/
a949f909 1785 memset(&priv->pmkid_list, 0, sizeof(struct host_if_pmkid_attr));
c5c77ba1
JK
1786
1787 return 0;
1788}
c5c77ba1 1789
c5c77ba1
JK
1790
1791/**
1792 * @brief WILC_WFI_CfgParseRxAction
1793 * @details Function parses the received frames and modifies the following attributes:
1794 * -GO Intent
1795 * -Channel list
1796 * -Operating Channel
1797 *
1798 * @param[in] u8* Buffer, u32 length
1799 * @return NONE.
1800 * @author mdaftedar
1801 * @date 12 DEC 2012
1802 * @version
1803 */
1804
4e4467fd 1805void WILC_WFI_CfgParseRxAction(u8 *buf, u32 len)
c5c77ba1 1806{
4e4467fd
CL
1807 u32 index = 0;
1808 u32 i = 0, j = 0;
c5c77ba1 1809
63d03e47
GKH
1810 u8 op_channel_attr_index = 0;
1811 u8 channel_list_attr_index = 0;
c5c77ba1
JK
1812
1813 while (index < len) {
1814 if (buf[index] == GO_INTENT_ATTR_ID) {
c5c77ba1 1815 buf[index + 3] = (buf[index + 3] & 0x01) | (0x00 << 1);
c5c77ba1
JK
1816 }
1817
78174ada 1818 if (buf[index] == CHANLIST_ATTR_ID)
c5c77ba1 1819 channel_list_attr_index = index;
78174ada 1820 else if (buf[index] == OPERCHAN_ATTR_ID)
c5c77ba1 1821 op_channel_attr_index = index;
c5c77ba1
JK
1822 index += buf[index + 1] + 3; /* ID,Length byte */
1823 }
3604af50 1824 if (u8WLANChannel != INVALID_CHANNEL) {
c5c77ba1 1825
c5c77ba1
JK
1826 /*Modify channel list attribute*/
1827 if (channel_list_attr_index) {
1828 PRINT_D(GENERIC_DBG, "Modify channel list attribute\n");
1829 for (i = channel_list_attr_index + 3; i < ((channel_list_attr_index + 3) + buf[channel_list_attr_index + 1]); i++) {
1830 if (buf[i] == 0x51) {
1831 for (j = i + 2; j < ((i + 2) + buf[i + 1]); j++) {
1832 buf[j] = u8WLANChannel;
1833 }
1834 break;
1835 }
1836 }
1837 }
1838 /*Modify operating channel attribute*/
1839 if (op_channel_attr_index) {
1840 PRINT_D(GENERIC_DBG, "Modify operating channel attribute\n");
1841 buf[op_channel_attr_index + 6] = 0x51;
1842 buf[op_channel_attr_index + 7] = u8WLANChannel;
1843 }
1844 }
1845}
1846
1847/**
1848 * @brief WILC_WFI_CfgParseTxAction
1849 * @details Function parses the transmitted action frames and modifies the
1850 * GO Intent attribute
1851 * @param[in] u8* Buffer, u32 length, bool bOperChan, u8 iftype
1852 * @return NONE.
1853 * @author mdaftedar
1854 * @date 12 DEC 2012
1855 * @version
1856 */
72ed4dc7 1857void WILC_WFI_CfgParseTxAction(u8 *buf, u32 len, bool bOperChan, u8 iftype)
c5c77ba1 1858{
4e4467fd
CL
1859 u32 index = 0;
1860 u32 i = 0, j = 0;
c5c77ba1 1861
63d03e47
GKH
1862 u8 op_channel_attr_index = 0;
1863 u8 channel_list_attr_index = 0;
c5c77ba1
JK
1864
1865 while (index < len) {
c5c77ba1 1866 if (buf[index] == GO_INTENT_ATTR_ID) {
c5c77ba1 1867 buf[index + 3] = (buf[index + 3] & 0x01) | (0x0f << 1);
c5c77ba1
JK
1868
1869 break;
1870 }
c5c77ba1 1871
78174ada 1872 if (buf[index] == CHANLIST_ATTR_ID)
c5c77ba1 1873 channel_list_attr_index = index;
78174ada 1874 else if (buf[index] == OPERCHAN_ATTR_ID)
c5c77ba1 1875 op_channel_attr_index = index;
c5c77ba1
JK
1876 index += buf[index + 1] + 3; /* ID,Length byte */
1877 }
3604af50 1878 if (u8WLANChannel != INVALID_CHANNEL && bOperChan) {
c5c77ba1 1879
c5c77ba1
JK
1880 /*Modify channel list attribute*/
1881 if (channel_list_attr_index) {
1882 PRINT_D(GENERIC_DBG, "Modify channel list attribute\n");
1883 for (i = channel_list_attr_index + 3; i < ((channel_list_attr_index + 3) + buf[channel_list_attr_index + 1]); i++) {
1884 if (buf[i] == 0x51) {
1885 for (j = i + 2; j < ((i + 2) + buf[i + 1]); j++) {
1886 buf[j] = u8WLANChannel;
1887 }
1888 break;
1889 }
1890 }
1891 }
1892 /*Modify operating channel attribute*/
1893 if (op_channel_attr_index) {
1894 PRINT_D(GENERIC_DBG, "Modify operating channel attribute\n");
1895 buf[op_channel_attr_index + 6] = 0x51;
1896 buf[op_channel_attr_index + 7] = u8WLANChannel;
1897 }
1898 }
1899}
1900
1901/* @brief WILC_WFI_p2p_rx
1902 * @details
1903 * @param[in]
1904 *
1905 * @return None
1906 * @author Mai Daftedar
1907 * @date 2 JUN 2013
1908 * @version 1.0
1909 */
1910
fbc2fe16 1911void WILC_WFI_p2p_rx (struct net_device *dev, u8 *buff, u32 size)
c5c77ba1
JK
1912{
1913
2726887c 1914 struct wilc_priv *priv;
4e4467fd 1915 u32 header, pkt_offset;
441dc609 1916 struct host_if_drv *pstrWFIDrv;
4e4467fd 1917 u32 i = 0;
fb4ec9ca 1918 s32 s32Freq;
8dfaafd6 1919
c5c77ba1 1920 priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
441dc609 1921 pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv;
c5c77ba1
JK
1922
1923 /* Get WILC header */
d00d2ba3 1924 memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET);
c5c77ba1
JK
1925
1926 /* The packet offset field conain info about what type of managment frame */
1927 /* we are dealing with and ack status */
1928 pkt_offset = GET_PKT_OFFSET(header);
1929
1930 if (pkt_offset & IS_MANAGMEMENT_CALLBACK) {
1931 if (buff[FRAME_TYPE_ID] == IEEE80211_STYPE_PROBE_RESP) {
1932 PRINT_D(GENERIC_DBG, "Probe response ACK\n");
c5c77ba1 1933 cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL);
c5c77ba1
JK
1934 return;
1935 } else {
1936 if (pkt_offset & IS_MGMT_STATUS_SUCCES) {
1937 PRINT_D(GENERIC_DBG, "Success Ack - Action frame category: %x Action Subtype: %d Dialog T: %x OR %x\n", buff[ACTION_CAT_ID], buff[ACTION_SUBTYPE_ID],
1938 buff[ACTION_SUBTYPE_ID + 1], buff[P2P_PUB_ACTION_SUBTYPE + 1]);
c5c77ba1 1939 cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL);
c5c77ba1
JK
1940 } else {
1941 PRINT_D(GENERIC_DBG, "Fail Ack - Action frame category: %x Action Subtype: %d Dialog T: %x OR %x\n", buff[ACTION_CAT_ID], buff[ACTION_SUBTYPE_ID],
1942 buff[ACTION_SUBTYPE_ID + 1], buff[P2P_PUB_ACTION_SUBTYPE + 1]);
c5c77ba1 1943 cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, false, GFP_KERNEL);
c5c77ba1
JK
1944 }
1945 return;
1946 }
1947 } else {
1948
1949 PRINT_D(GENERIC_DBG, "Rx Frame Type:%x\n", buff[FRAME_TYPE_ID]);
1950
c5c77ba1 1951 /*Upper layer is informed that the frame is received on this freq*/
866a2c24 1952 s32Freq = ieee80211_channel_to_frequency(curr_channel, IEEE80211_BAND_2GHZ);
c5c77ba1
JK
1953
1954 if (ieee80211_is_action(buff[FRAME_TYPE_ID])) {
1955 PRINT_D(GENERIC_DBG, "Rx Action Frame Type: %x %x\n", buff[ACTION_SUBTYPE_ID], buff[P2P_PUB_ACTION_SUBTYPE]);
1956
1229b1ab 1957 if (priv->bCfgScanning && time_after_eq(jiffies, (unsigned long)pstrWFIDrv->p2p_timeout)) {
c5c77ba1
JK
1958 PRINT_D(GENERIC_DBG, "Receiving action frames from wrong channels\n");
1959 return;
1960 }
1961 if (buff[ACTION_CAT_ID] == PUB_ACTION_ATTR_ID) {
1962
1963 switch (buff[ACTION_SUBTYPE_ID]) {
1964 case GAS_INTIAL_REQ:
1965 PRINT_D(GENERIC_DBG, "GAS INITIAL REQ %x\n", buff[ACTION_SUBTYPE_ID]);
1966 break;
1967
1968 case GAS_INTIAL_RSP:
1969 PRINT_D(GENERIC_DBG, "GAS INITIAL RSP %x\n", buff[ACTION_SUBTYPE_ID]);
1970 break;
1971
1972 case PUBLIC_ACT_VENDORSPEC:
1973 /*Now we have a public action vendor specific action frame, check if its a p2p public action frame
1974 * based on the standard its should have the p2p_oui attribute with the following values 50 6f 9A 09*/
1a646e7e 1975 if (!memcmp(u8P2P_oui, &buff[ACTION_SUBTYPE_ID + 1], 4)) {
c5c77ba1
JK
1976 if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP)) {
1977 if (!bWilc_ie) {
1978 for (i = P2P_PUB_ACTION_SUBTYPE; i < size; i++) {
1a646e7e 1979 if (!memcmp(u8P2P_vendorspec, &buff[i], 6)) {
c5c77ba1 1980 u8P2Precvrandom = buff[i + 6];
72ed4dc7 1981 bWilc_ie = true;
c5c77ba1
JK
1982 PRINT_D(GENERIC_DBG, "WILC Vendor specific IE:%02x\n", u8P2Precvrandom);
1983 break;
1984 }
1985 }
1986 }
1987 }
1988 if (u8P2Plocalrandom > u8P2Precvrandom) {
1989 if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP
1990 || buff[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)) {
1991 for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < size; i++) {
1a646e7e 1992 if (buff[i] == P2PELEM_ATTR_ID && !(memcmp(u8P2P_oui, &buff[i + 2], 4))) {
c5c77ba1
JK
1993 WILC_WFI_CfgParseRxAction(&buff[i + 6], size - (i + 6));
1994 break;
1995 }
1996 }
1997 }
1998 } else
1999 PRINT_D(GENERIC_DBG, "PEER WILL BE GO LocaRand=%02x RecvRand %02x\n", u8P2Plocalrandom, u8P2Precvrandom);
2000 }
2001
2002
2003 if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP) && (bWilc_ie)) {
2004 PRINT_D(GENERIC_DBG, "Sending P2P to host without extra elemnt\n");
2005 /* extra attribute for sig_dbm: signal strength in mBm, or 0 if unknown */
c5c77ba1 2006 cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size - 7, 0);
c5c77ba1
JK
2007 return;
2008 }
2009 break;
2010
2011 default:
2012 PRINT_D(GENERIC_DBG, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buff[ACTION_SUBTYPE_ID]);
2013 break;
2014 }
2015 }
2016 }
2017
c5c77ba1 2018 cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size - 7, 0);
c5c77ba1
JK
2019 }
2020}
2021
2022/**
2023 * @brief WILC_WFI_mgmt_tx_complete
2024 * @details Returns result of writing mgmt frame to VMM (Tx buffers are freed here)
2025 * @param[in] priv
2026 * transmitting status
2027 * @return None
2028 * @author Amr Abdelmoghny
2029 * @date 20 MAY 2013
2030 * @version 1.0
2031 */
2032static void WILC_WFI_mgmt_tx_complete(void *priv, int status)
2033{
2034 struct p2p_mgmt_data *pv_data = (struct p2p_mgmt_data *)priv;
2035
2036
2037 kfree(pv_data->buff);
2038 kfree(pv_data);
2039}
2040
2041/**
2042 * @brief WILC_WFI_RemainOnChannelReady
2043 * @details Callback function, called from handle_remain_on_channel on being ready on channel
2044 * @param
2045 * @return none
2046 * @author Amr abdelmoghny
2047 * @date 9 JUNE 2013
2048 * @version
2049 */
2050
2051static void WILC_WFI_RemainOnChannelReady(void *pUserVoid)
2052{
2726887c 2053 struct wilc_priv *priv;
8dfaafd6 2054
2726887c 2055 priv = (struct wilc_priv *)pUserVoid;
c5c77ba1 2056
17aacd43 2057 PRINT_D(HOSTINF_DBG, "Remain on channel ready\n");
c5c77ba1 2058
72ed4dc7 2059 priv->bInP2PlistenState = true;
c5c77ba1 2060
c5c77ba1
JK
2061 cfg80211_ready_on_channel(priv->wdev,
2062 priv->strRemainOnChanParams.u64ListenCookie,
2063 priv->strRemainOnChanParams.pstrListenChan,
2064 priv->strRemainOnChanParams.u32ListenDuration,
2065 GFP_KERNEL);
c5c77ba1
JK
2066}
2067
2068/**
2069 * @brief WILC_WFI_RemainOnChannelExpired
2070 * @details Callback function, called on expiration of remain-on-channel duration
2071 * @param
2072 * @return none
2073 * @author Amr abdelmoghny
2074 * @date 15 MAY 2013
2075 * @version
2076 */
2077
4e4467fd 2078static void WILC_WFI_RemainOnChannelExpired(void *pUserVoid, u32 u32SessionID)
c5c77ba1 2079{
2726887c 2080 struct wilc_priv *priv;
8dfaafd6 2081
2726887c 2082 priv = (struct wilc_priv *)pUserVoid;
c5c77ba1 2083
c5c77ba1 2084 if (u32SessionID == priv->strRemainOnChanParams.u32ListenSessionID) {
17aacd43 2085 PRINT_D(GENERIC_DBG, "Remain on channel expired\n");
c5c77ba1 2086
72ed4dc7 2087 priv->bInP2PlistenState = false;
c5c77ba1
JK
2088
2089 /*Inform wpas of remain-on-channel expiration*/
c5c77ba1
JK
2090 cfg80211_remain_on_channel_expired(priv->wdev,
2091 priv->strRemainOnChanParams.u64ListenCookie,
2092 priv->strRemainOnChanParams.pstrListenChan,
2093 GFP_KERNEL);
c5c77ba1
JK
2094 } else {
2095 PRINT_D(GENERIC_DBG, "Received ID 0x%x Expected ID 0x%x (No match)\n", u32SessionID
2096 , priv->strRemainOnChanParams.u32ListenSessionID);
2097 }
2098}
2099
2100
2101/**
6d19d695 2102 * @brief remain_on_channel
c5c77ba1
JK
2103 * @details Request the driver to remain awake on the specified
2104 * channel for the specified duration to complete an off-channel
2105 * operation (e.g., public action frame exchange). When the driver is
2106 * ready on the requested channel, it must indicate this with an event
2107 * notification by calling cfg80211_ready_on_channel().
2108 * @param[in]
2109 * @return int : Return 0 on Success
2110 * @author mdaftedar
2111 * @date 01 MAR 2012
2112 * @version 1.0
2113 */
6d19d695
CL
2114static int remain_on_channel(struct wiphy *wiphy,
2115 struct wireless_dev *wdev,
2116 struct ieee80211_channel *chan,
2117 unsigned int duration, u64 *cookie)
c5c77ba1 2118{
e6e12661 2119 s32 s32Error = 0;
2726887c 2120 struct wilc_priv *priv;
8dfaafd6 2121
c5c77ba1
JK
2122 priv = wiphy_priv(wiphy);
2123
2124 PRINT_D(GENERIC_DBG, "Remaining on channel %d\n", chan->hw_value);
2125
c5c77ba1 2126
c5c77ba1
JK
2127 if (wdev->iftype == NL80211_IFTYPE_AP) {
2128 PRINT_D(GENERIC_DBG, "Required remain-on-channel while in AP mode");
2129 return s32Error;
2130 }
c5c77ba1 2131
866a2c24 2132 curr_channel = chan->hw_value;
c5c77ba1
JK
2133
2134 /*Setting params needed by WILC_WFI_RemainOnChannelExpired()*/
2135 priv->strRemainOnChanParams.pstrListenChan = chan;
2136 priv->strRemainOnChanParams.u64ListenCookie = *cookie;
c5c77ba1
JK
2137 priv->strRemainOnChanParams.u32ListenDuration = duration;
2138 priv->strRemainOnChanParams.u32ListenSessionID++;
2139
2140 s32Error = host_int_remain_on_channel(priv->hWILCWFIDrv
2141 , priv->strRemainOnChanParams.u32ListenSessionID
2142 , duration
2143 , chan->hw_value
2144 , WILC_WFI_RemainOnChannelExpired
2145 , WILC_WFI_RemainOnChannelReady
2146 , (void *)priv);
2147
2148 return s32Error;
2149}
2150
2151/**
1dd5440b 2152 * @brief cancel_remain_on_channel
c5c77ba1
JK
2153 * @details Cancel an on-going remain-on-channel operation.
2154 * This allows the operation to be terminated prior to timeout based on
2155 * the duration value.
2156 * @param[in] struct wiphy *wiphy,
2157 * @param[in] struct net_device *dev
2158 * @param[in] u64 cookie,
2159 * @return int : Return 0 on Success
2160 * @author mdaftedar
2161 * @date 01 MAR 2012
2162 * @version 1.0
2163 */
1dd5440b
CL
2164static int cancel_remain_on_channel(struct wiphy *wiphy,
2165 struct wireless_dev *wdev,
2166 u64 cookie)
c5c77ba1 2167{
e6e12661 2168 s32 s32Error = 0;
2726887c 2169 struct wilc_priv *priv;
8dfaafd6 2170
c5c77ba1
JK
2171 priv = wiphy_priv(wiphy);
2172
2173 PRINT_D(CFG80211_DBG, "Cancel remain on channel\n");
2174
2175 s32Error = host_int_ListenStateExpired(priv->hWILCWFIDrv, priv->strRemainOnChanParams.u32ListenSessionID);
2176 return s32Error;
2177}
c5c77ba1
JK
2178/**
2179 * @brief WILC_WFI_mgmt_tx_frame
2180 * @details
2181 *
2182 * @param[in]
2183 * @return NONE.
2184 * @author mdaftedar
2185 * @date 01 JUL 2012
2186 * @version
2187 */
72ed4dc7 2188extern bool bEnablePS;
c156032d
CL
2189static int mgmt_tx(struct wiphy *wiphy,
2190 struct wireless_dev *wdev,
2191 struct cfg80211_mgmt_tx_params *params,
2192 u64 *cookie)
c5c77ba1 2193{
c5c77ba1
JK
2194 struct ieee80211_channel *chan = params->chan;
2195 unsigned int wait = params->wait;
2196 const u8 *buf = params->buf;
2197 size_t len = params->len;
c5c77ba1
JK
2198 const struct ieee80211_mgmt *mgmt;
2199 struct p2p_mgmt_data *mgmt_tx;
2726887c 2200 struct wilc_priv *priv;
441dc609 2201 struct host_if_drv *pstrWFIDrv;
4e4467fd 2202 u32 i;
c5c77ba1 2203 perInterface_wlan_t *nic;
4e4467fd 2204 u32 buf_len = len + sizeof(u8P2P_vendorspec) + sizeof(u8P2Plocalrandom);
c5c77ba1 2205
c5c77ba1 2206 nic = netdev_priv(wdev->netdev);
c5c77ba1 2207 priv = wiphy_priv(wiphy);
441dc609 2208 pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv;
c5c77ba1
JK
2209
2210 *cookie = (unsigned long)buf;
2211 priv->u64tx_cookie = *cookie;
2212 mgmt = (const struct ieee80211_mgmt *) buf;
2213
2214 if (ieee80211_is_mgmt(mgmt->frame_control)) {
2215
2216 /*mgmt frame allocation*/
f3052587 2217 mgmt_tx = kmalloc(sizeof(struct p2p_mgmt_data), GFP_KERNEL);
c5c77ba1
JK
2218 if (mgmt_tx == NULL) {
2219 PRINT_ER("Failed to allocate memory for mgmt_tx structure\n");
e6e12661 2220 return -EFAULT;
c5c77ba1 2221 }
f3052587 2222 mgmt_tx->buff = kmalloc(buf_len, GFP_KERNEL);
c5c77ba1
JK
2223 if (mgmt_tx->buff == NULL) {
2224 PRINT_ER("Failed to allocate memory for mgmt_tx buff\n");
f638dd39 2225 kfree(mgmt_tx);
e6e12661 2226 return -EFAULT;
c5c77ba1 2227 }
d00d2ba3 2228 memcpy(mgmt_tx->buff, buf, len);
c5c77ba1
JK
2229 mgmt_tx->size = len;
2230
2231
2232 if (ieee80211_is_probe_resp(mgmt->frame_control)) {
2233 PRINT_D(GENERIC_DBG, "TX: Probe Response\n");
2234 PRINT_D(GENERIC_DBG, "Setting channel: %d\n", chan->hw_value);
2235 host_int_set_mac_chnl_num(priv->hWILCWFIDrv, chan->hw_value);
2236 /*Save the current channel after we tune to it*/
866a2c24 2237 curr_channel = chan->hw_value;
c5c77ba1 2238 } else if (ieee80211_is_action(mgmt->frame_control)) {
d85f5326 2239 PRINT_D(GENERIC_DBG, "ACTION FRAME:%x\n", (u16)mgmt->frame_control);
c5c77ba1
JK
2240
2241
c5c77ba1 2242 if (buf[ACTION_CAT_ID] == PUB_ACTION_ATTR_ID) {
c5c77ba1
JK
2243 /*Only set the channel, if not a negotiation confirmation frame
2244 * (If Negotiation confirmation frame, force it
2245 * to be transmitted on the same negotiation channel)*/
2246
2247 if (buf[ACTION_SUBTYPE_ID] != PUBLIC_ACT_VENDORSPEC ||
2248 buf[P2P_PUB_ACTION_SUBTYPE] != GO_NEG_CONF) {
2249 PRINT_D(GENERIC_DBG, "Setting channel: %d\n", chan->hw_value);
2250 host_int_set_mac_chnl_num(priv->hWILCWFIDrv, chan->hw_value);
2251 /*Save the current channel after we tune to it*/
866a2c24 2252 curr_channel = chan->hw_value;
c5c77ba1
JK
2253 }
2254 switch (buf[ACTION_SUBTYPE_ID]) {
2255 case GAS_INTIAL_REQ:
2256 {
2257 PRINT_D(GENERIC_DBG, "GAS INITIAL REQ %x\n", buf[ACTION_SUBTYPE_ID]);
2258 break;
2259 }
2260
2261 case GAS_INTIAL_RSP:
2262 {
2263 PRINT_D(GENERIC_DBG, "GAS INITIAL RSP %x\n", buf[ACTION_SUBTYPE_ID]);
2264 break;
2265 }
2266
2267 case PUBLIC_ACT_VENDORSPEC:
2268 {
2269 /*Now we have a public action vendor specific action frame, check if its a p2p public action frame
2270 * based on the standard its should have the p2p_oui attribute with the following values 50 6f 9A 09*/
1a646e7e 2271 if (!memcmp(u8P2P_oui, &buf[ACTION_SUBTYPE_ID + 1], 4)) {
c5c77ba1
JK
2272 /*For the connection of two WILC's connection generate a rand number to determine who will be a GO*/
2273 if ((buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP)) {
2274 if (u8P2Plocalrandom == 1 && u8P2Precvrandom < u8P2Plocalrandom) {
2275 get_random_bytes(&u8P2Plocalrandom, 1);
2276 /*Increment the number to prevent if its 0*/
2277 u8P2Plocalrandom++;
2278 }
2279 }
2280
2281 if ((buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP
2282 || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)) {
2283 if (u8P2Plocalrandom > u8P2Precvrandom) {
2284 PRINT_D(GENERIC_DBG, "LOCAL WILL BE GO LocaRand=%02x RecvRand %02x\n", u8P2Plocalrandom, u8P2Precvrandom);
2285
2286 /*Search for the p2p information information element , after the Public action subtype theres a byte for teh dialog token, skip that*/
2287 for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < len; i++) {
1a646e7e 2288 if (buf[i] == P2PELEM_ATTR_ID && !(memcmp(u8P2P_oui, &buf[i + 2], 4))) {
c5c77ba1 2289 if (buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)
72ed4dc7 2290 WILC_WFI_CfgParseTxAction(&mgmt_tx->buff[i + 6], len - (i + 6), true, nic->iftype);
c5c77ba1 2291
c5c77ba1
JK
2292 /*If using supplicant go intent, no need at all*/
2293 /*to parse transmitted negotiation frames*/
c5c77ba1 2294 else
72ed4dc7 2295 WILC_WFI_CfgParseTxAction(&mgmt_tx->buff[i + 6], len - (i + 6), false, nic->iftype);
c5c77ba1
JK
2296 break;
2297 }
2298 }
2299
2300 if (buf[P2P_PUB_ACTION_SUBTYPE] != P2P_INV_REQ && buf[P2P_PUB_ACTION_SUBTYPE] != P2P_INV_RSP) {
d8060fc0
SB
2301 /*
2302 * Adding WILC information element to allow two WILC devices to
2303 * identify each other and connect
2304 */
2305 memcpy(&mgmt_tx->buff[len], u8P2P_vendorspec, sizeof(u8P2P_vendorspec));
c5c77ba1
JK
2306 mgmt_tx->buff[len + sizeof(u8P2P_vendorspec)] = u8P2Plocalrandom;
2307 mgmt_tx->size = buf_len;
2308 }
2309 } else
2310 PRINT_D(GENERIC_DBG, "PEER WILL BE GO LocaRand=%02x RecvRand %02x\n", u8P2Plocalrandom, u8P2Precvrandom);
2311 }
2312
2313 } else {
2314 PRINT_D(GENERIC_DBG, "Not a P2P public action frame\n");
2315 }
2316
2317 break;
2318 }
2319
2320 default:
2321 {
2322 PRINT_D(GENERIC_DBG, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buf[ACTION_SUBTYPE_ID]);
2323 break;
2324 }
2325 }
2326
2327 }
2328
2329 PRINT_D(GENERIC_DBG, "TX: ACTION FRAME Type:%x : Chan:%d\n", buf[ACTION_SUBTYPE_ID], chan->hw_value);
1229b1ab 2330 pstrWFIDrv->p2p_timeout = (jiffies + msecs_to_jiffies(wait));
c5c77ba1 2331
1229b1ab
LK
2332 PRINT_D(GENERIC_DBG, "Current Jiffies: %lu Timeout:%llu\n",
2333 jiffies, pstrWFIDrv->p2p_timeout);
c5c77ba1
JK
2334 }
2335
829c477f
GL
2336 wilc_wlan_txq_add_mgmt_pkt(wdev->netdev, mgmt_tx,
2337 mgmt_tx->buff, mgmt_tx->size,
c9d4834d 2338 WILC_WFI_mgmt_tx_complete);
c5c77ba1
JK
2339 } else {
2340 PRINT_D(GENERIC_DBG, "This function transmits only management frames\n");
2341 }
aaed3290 2342 return 0;
c5c77ba1
JK
2343}
2344
85c587a5
CL
2345static int mgmt_tx_cancel_wait(struct wiphy *wiphy,
2346 struct wireless_dev *wdev,
2347 u64 cookie)
c5c77ba1 2348{
2726887c 2349 struct wilc_priv *priv;
441dc609 2350 struct host_if_drv *pstrWFIDrv;
8dfaafd6 2351
c5c77ba1 2352 priv = wiphy_priv(wiphy);
441dc609 2353 pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv;
c5c77ba1
JK
2354
2355
2356 PRINT_D(GENERIC_DBG, "Tx Cancel wait :%lu\n", jiffies);
1229b1ab 2357 pstrWFIDrv->p2p_timeout = jiffies;
c5c77ba1 2358
7e4e87d3 2359 if (!priv->bInP2PlistenState) {
c5c77ba1
JK
2360 cfg80211_remain_on_channel_expired(priv->wdev,
2361 priv->strRemainOnChanParams.u64ListenCookie,
2362 priv->strRemainOnChanParams.pstrListenChan,
2363 GFP_KERNEL);
c5c77ba1
JK
2364 }
2365
2366 return 0;
2367}
2368
c5c77ba1 2369/**
8e0735c5 2370 * @brief wilc_mgmt_frame_register
c5c77ba1
JK
2371 * @details Notify driver that a management frame type was
2372 * registered. Note that this callback may not sleep, and cannot run
2373 * concurrently with itself.
2374 * @param[in]
2375 * @return NONE.
2376 * @author mdaftedar
2377 * @date 01 JUL 2012
2378 * @version
2379 */
8e0735c5
CL
2380void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev,
2381 u16 frame_type, bool reg)
c5c77ba1
JK
2382{
2383
2726887c 2384 struct wilc_priv *priv;
c5c77ba1 2385 perInterface_wlan_t *nic;
1b86935e 2386 struct wilc *wl;
c5c77ba1
JK
2387
2388 priv = wiphy_priv(wiphy);
2389 nic = netdev_priv(priv->wdev->netdev);
1b86935e 2390 wl = nic->wilc;
c5c77ba1 2391
c5c77ba1
JK
2392 if (!frame_type)
2393 return;
2394
2395 PRINT_D(GENERIC_DBG, "Frame registering Frame Type: %x: Boolean: %d\n", frame_type, reg);
2396 switch (frame_type) {
2397 case PROBE_REQ:
2398 {
2399 nic->g_struct_frame_reg[0].frame_type = frame_type;
2400 nic->g_struct_frame_reg[0].reg = reg;
2401 }
2402 break;
2403
2404 case ACTION:
2405 {
2406 nic->g_struct_frame_reg[1].frame_type = frame_type;
2407 nic->g_struct_frame_reg[1].reg = reg;
2408 }
2409 break;
2410
2411 default:
2412 {
2413 break;
2414 }
2415
2416 }
2417 /*If mac is closed, then return*/
1b86935e 2418 if (!wl->initialized) {
c5c77ba1
JK
2419 PRINT_D(GENERIC_DBG, "Return since mac is closed\n");
2420 return;
2421 }
2422 host_int_frame_register(priv->hWILCWFIDrv, frame_type, reg);
2423
2424
2425}
c5c77ba1
JK
2426
2427/**
a8047e26 2428 * @brief set_cqm_rssi_config
c5c77ba1
JK
2429 * @details Configure connection quality monitor RSSI threshold.
2430 * @param[in] struct wiphy *wiphy:
2431 * @param[in] struct net_device *dev:
2432 * @param[in] s32 rssi_thold:
2433 * @param[in] u32 rssi_hyst:
2434 * @return int : Return 0 on Success
2435 * @author mdaftedar
2436 * @date 01 MAR 2012
2437 * @version 1.0
2438 */
a8047e26
CL
2439static int set_cqm_rssi_config(struct wiphy *wiphy, struct net_device *dev,
2440 s32 rssi_thold, u32 rssi_hyst)
c5c77ba1
JK
2441{
2442 PRINT_D(CFG80211_DBG, "Setting CQM RSSi Function\n");
2443 return 0;
2444
2445}
2446/**
bdb6338f 2447 * @brief dump_station
c5c77ba1
JK
2448 * @details Configure connection quality monitor RSSI threshold.
2449 * @param[in] struct wiphy *wiphy:
2450 * @param[in] struct net_device *dev
2451 * @param[in] int idx
2452 * @param[in] u8 *mac
2453 * @param[in] struct station_info *sinfo
2454 * @return int : Return 0 on Success
2455 * @author mdaftedar
2456 * @date 01 MAR 2012
2457 * @version 1.0
2458 */
bdb6338f
CL
2459static int dump_station(struct wiphy *wiphy, struct net_device *dev,
2460 int idx, u8 *mac, struct station_info *sinfo)
c5c77ba1 2461{
2726887c 2462 struct wilc_priv *priv;
8dfaafd6 2463
c5c77ba1
JK
2464 PRINT_D(CFG80211_DBG, "Dumping station information\n");
2465
2466 if (idx != 0)
2467 return -ENOENT;
2468
2469 priv = wiphy_priv(wiphy);
c5c77ba1 2470
c5c77ba1 2471 sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
c5c77ba1
JK
2472
2473 host_int_get_rssi(priv->hWILCWFIDrv, &(sinfo->signal));
2474
c5c77ba1
JK
2475 return 0;
2476
2477}
2478
2479
2480/**
46530679 2481 * @brief set_power_mgmt
c5c77ba1
JK
2482 * @details
2483 * @param[in]
2484 * @return int : Return 0 on Success.
2485 * @author mdaftedar
2486 * @date 01 JUL 2012
cdc9cba5 2487 * @version 1.0
c5c77ba1 2488 */
46530679
CL
2489static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
2490 bool enabled, int timeout)
c5c77ba1 2491{
2726887c 2492 struct wilc_priv *priv;
8dfaafd6 2493
c5c77ba1
JK
2494 PRINT_D(CFG80211_DBG, " Power save Enabled= %d , TimeOut = %d\n", enabled, timeout);
2495
b1413b60 2496 if (wiphy == NULL)
c5c77ba1
JK
2497 return -ENOENT;
2498
2499 priv = wiphy_priv(wiphy);
b1413b60 2500 if (priv->hWILCWFIDrv == NULL) {
c5c77ba1
JK
2501 PRINT_ER("Driver is NULL\n");
2502 return -EIO;
2503 }
2504
5a66bf20 2505 if (bEnablePS)
c5c77ba1
JK
2506 host_int_set_power_mgmt(priv->hWILCWFIDrv, enabled, timeout);
2507
2508
e6e12661 2509 return 0;
c5c77ba1
JK
2510
2511}
108b3439 2512
c5c77ba1 2513/**
3615e9a3 2514 * @brief change_virtual_intf
c5c77ba1
JK
2515 * @details Change type/configuration of virtual interface,
2516 * keep the struct wireless_dev's iftype updated.
2517 * @param[in] NONE
2518 * @return int : Return 0 on Success.
2519 * @author mdaftedar
2520 * @date 01 MAR 2012
2521 * @version 1.0
2522 */
c5c77ba1
JK
2523int wilc1000_wlan_init(struct net_device *dev, perInterface_wlan_t *p_nic);
2524
3615e9a3
CL
2525static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
2526 enum nl80211_iftype type, u32 *flags, struct vif_params *params)
c5c77ba1 2527{
2726887c 2528 struct wilc_priv *priv;
c5c77ba1 2529 perInterface_wlan_t *nic;
63d03e47 2530 u8 interface_type;
d85f5326 2531 u16 TID = 0;
63d03e47 2532 u8 i;
299382cf 2533 struct wilc *wl;
c5c77ba1
JK
2534
2535 nic = netdev_priv(dev);
2536 priv = wiphy_priv(wiphy);
299382cf 2537 wl = nic->wilc;
c5c77ba1
JK
2538
2539 PRINT_D(HOSTAPD_DBG, "In Change virtual interface function\n");
2540 PRINT_D(HOSTAPD_DBG, "Wireless interface name =%s\n", dev->name);
2541 u8P2Plocalrandom = 0x01;
2542 u8P2Precvrandom = 0x00;
2543
72ed4dc7 2544 bWilc_ie = false;
c5c77ba1 2545
72ed4dc7 2546 g_obtainingIP = false;
8972d0fe 2547 del_timer(&hDuringIpTimer);
c5c77ba1 2548 PRINT_D(GENERIC_DBG, "Changing virtual interface, enable scan\n");
c5c77ba1
JK
2549 /*Set WILC_CHANGING_VIR_IF register to disallow adding futrue keys to CE H/W*/
2550 if (g_ptk_keys_saved && g_gtk_keys_saved) {
2ad8c47d 2551 set_machw_change_vir_if(dev, true);
c5c77ba1
JK
2552 }
2553
2554 switch (type) {
2555 case NL80211_IFTYPE_STATION:
2556 connecting = 0;
2557 PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_STATION\n");
c5c77ba1
JK
2558
2559 /* send delba over wlan interface */
2560
2561
2562 dev->ieee80211_ptr->iftype = type;
2563 priv->wdev->iftype = type;
2564 nic->monitor_flag = 0;
2565 nic->iftype = STATION_MODE;
2566
2567 /*Remove the enteries of the previously connected clients*/
2568 memset(priv->assoc_stainfo.au8Sta_AssociatedBss, 0, MAX_NUM_STA * ETH_ALEN);
c5c77ba1
JK
2569 interface_type = nic->iftype;
2570 nic->iftype = STATION_MODE;
2571
299382cf
GL
2572 if (wl->initialized) {
2573 host_int_del_All_Rx_BASession(priv->hWILCWFIDrv,
2574 wl->vif[0].bssid, TID);
c5c77ba1
JK
2575 /* ensure that the message Q is empty */
2576 host_int_wait_msg_queue_idle();
2577
c5c77ba1 2578 /*Eliminate host interface blocking state*/
299382cf 2579 up(&wl->cfg_event);
c5c77ba1 2580
53dc0cfe 2581 wilc1000_wlan_deinit(dev);
c5c77ba1
JK
2582 wilc1000_wlan_init(dev, nic);
2583 g_wilc_initialized = 1;
2584 nic->iftype = interface_type;
2585
2586 /*Setting interface 1 drv handler and mac address in newly downloaded FW*/
299382cf
GL
2587 host_int_set_wfi_drv_handler(wl->vif[0].hif_drv);
2588 host_int_set_MacAddress(wl->vif[0].hif_drv,
2589 wl->vif[0].src_addr);
c5c77ba1
JK
2590 host_int_set_operation_mode(priv->hWILCWFIDrv, STATION_MODE);
2591
2592 /*Add saved WEP keys, if any*/
2593 if (g_wep_keys_saved) {
df8b4830 2594 host_int_set_wep_default_key(wl->vif[0].hif_drv,
c5c77ba1 2595 g_key_wep_params.key_idx);
299382cf 2596 host_int_add_wep_key_bss_sta(wl->vif[0].hif_drv,
c5c77ba1
JK
2597 g_key_wep_params.key,
2598 g_key_wep_params.key_len,
2599 g_key_wep_params.key_idx);
2600 }
2601
2602 /*No matter the driver handler passed here, it will be overwriiten*/
2603 /*in Handle_FlushConnect() with gu8FlushedJoinReqDrvHandler*/
2604 host_int_flush_join_req(priv->hWILCWFIDrv);
2605
2606 /*Add saved PTK and GTK keys, if any*/
2607 if (g_ptk_keys_saved && g_gtk_keys_saved) {
2608 PRINT_D(CFG80211_DBG, "ptk %x %x %x\n", g_key_ptk_params.key[0],
2609 g_key_ptk_params.key[1],
2610 g_key_ptk_params.key[2]);
2611 PRINT_D(CFG80211_DBG, "gtk %x %x %x\n", g_key_gtk_params.key[0],
2612 g_key_gtk_params.key[1],
2613 g_key_gtk_params.key[2]);
299382cf
GL
2614 add_key(wl->vif[0].ndev->ieee80211_ptr->wiphy,
2615 wl->vif[0].ndev,
953d417a
CL
2616 g_add_ptk_key_params.key_idx,
2617 g_add_ptk_key_params.pairwise,
2618 g_add_ptk_key_params.mac_addr,
2619 (struct key_params *)(&g_key_ptk_params));
2620
299382cf
GL
2621 add_key(wl->vif[0].ndev->ieee80211_ptr->wiphy,
2622 wl->vif[0].ndev,
953d417a
CL
2623 g_add_gtk_key_params.key_idx,
2624 g_add_gtk_key_params.pairwise,
2625 g_add_gtk_key_params.mac_addr,
2626 (struct key_params *)(&g_key_gtk_params));
c5c77ba1
JK
2627 }
2628
299382cf 2629 if (wl->initialized) {
c5c77ba1
JK
2630 for (i = 0; i < num_reg_frame; i++) {
2631 PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", nic->g_struct_frame_reg[i].frame_type,
2632 nic->g_struct_frame_reg[i].reg);
2633 host_int_frame_register(priv->hWILCWFIDrv,
2634 nic->g_struct_frame_reg[i].frame_type,
2635 nic->g_struct_frame_reg[i].reg);
2636 }
2637 }
2638
72ed4dc7 2639 bEnablePS = true;
c5c77ba1
JK
2640 host_int_set_power_mgmt(priv->hWILCWFIDrv, 1, 0);
2641 }
c5c77ba1
JK
2642 break;
2643
2644 case NL80211_IFTYPE_P2P_CLIENT:
72ed4dc7 2645 bEnablePS = false;
c5c77ba1
JK
2646 host_int_set_power_mgmt(priv->hWILCWFIDrv, 0, 0);
2647 connecting = 0;
2648 PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_P2P_CLIENT\n");
c5c77ba1 2649
299382cf
GL
2650 host_int_del_All_Rx_BASession(priv->hWILCWFIDrv,
2651 wl->vif[0].bssid, TID);
c5c77ba1
JK
2652
2653 dev->ieee80211_ptr->iftype = type;
2654 priv->wdev->iftype = type;
2655 nic->monitor_flag = 0;
2656
c5c77ba1
JK
2657 PRINT_D(HOSTAPD_DBG, "Downloading P2P_CONCURRENCY_FIRMWARE\n");
2658 nic->iftype = CLIENT_MODE;
2659
2660
299382cf 2661 if (wl->initialized) {
c5c77ba1
JK
2662 /* ensure that the message Q is empty */
2663 host_int_wait_msg_queue_idle();
2664
53dc0cfe 2665 wilc1000_wlan_deinit(dev);
c5c77ba1
JK
2666 wilc1000_wlan_init(dev, nic);
2667 g_wilc_initialized = 1;
2668
299382cf
GL
2669 host_int_set_wfi_drv_handler(wl->vif[0].hif_drv);
2670 host_int_set_MacAddress(wl->vif[0].hif_drv,
2671 wl->vif[0].src_addr);
c5c77ba1
JK
2672 host_int_set_operation_mode(priv->hWILCWFIDrv, STATION_MODE);
2673
2674 /*Add saved WEP keys, if any*/
2675 if (g_wep_keys_saved) {
df8b4830 2676 host_int_set_wep_default_key(wl->vif[0].hif_drv,
c5c77ba1 2677 g_key_wep_params.key_idx);
299382cf 2678 host_int_add_wep_key_bss_sta(wl->vif[0].hif_drv,
c5c77ba1
JK
2679 g_key_wep_params.key,
2680 g_key_wep_params.key_len,
2681 g_key_wep_params.key_idx);
2682 }
2683
2684 /*No matter the driver handler passed here, it will be overwriiten*/
2685 /*in Handle_FlushConnect() with gu8FlushedJoinReqDrvHandler*/
2686 host_int_flush_join_req(priv->hWILCWFIDrv);
2687
2688 /*Add saved PTK and GTK keys, if any*/
2689 if (g_ptk_keys_saved && g_gtk_keys_saved) {
2690 PRINT_D(CFG80211_DBG, "ptk %x %x %x\n", g_key_ptk_params.key[0],
2691 g_key_ptk_params.key[1],
2692 g_key_ptk_params.key[2]);
2693 PRINT_D(CFG80211_DBG, "gtk %x %x %x\n", g_key_gtk_params.key[0],
2694 g_key_gtk_params.key[1],
2695 g_key_gtk_params.key[2]);
299382cf
GL
2696 add_key(wl->vif[0].ndev->ieee80211_ptr->wiphy,
2697 wl->vif[0].ndev,
953d417a
CL
2698 g_add_ptk_key_params.key_idx,
2699 g_add_ptk_key_params.pairwise,
2700 g_add_ptk_key_params.mac_addr,
2701 (struct key_params *)(&g_key_ptk_params));
2702
299382cf
GL
2703 add_key(wl->vif[0].ndev->ieee80211_ptr->wiphy,
2704 wl->vif[0].ndev,
953d417a
CL
2705 g_add_gtk_key_params.key_idx,
2706 g_add_gtk_key_params.pairwise,
2707 g_add_gtk_key_params.mac_addr,
2708 (struct key_params *)(&g_key_gtk_params));
c5c77ba1
JK
2709 }
2710
2711 /*Refresh scan, to refresh the scan results to the wpa_supplicant. Set MachHw to false to enable further key installments*/
72ed4dc7 2712 refresh_scan(priv, 1, true);
2ad8c47d 2713 set_machw_change_vir_if(dev, false);
c5c77ba1 2714
299382cf 2715 if (wl->initialized) {
c5c77ba1
JK
2716 for (i = 0; i < num_reg_frame; i++) {
2717 PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", nic->g_struct_frame_reg[i].frame_type,
2718 nic->g_struct_frame_reg[i].reg);
2719 host_int_frame_register(priv->hWILCWFIDrv,
2720 nic->g_struct_frame_reg[i].frame_type,
2721 nic->g_struct_frame_reg[i].reg);
2722 }
2723 }
2724 }
c5c77ba1
JK
2725 break;
2726
2727 case NL80211_IFTYPE_AP:
72ed4dc7 2728 bEnablePS = false;
c5c77ba1 2729 PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_AP %d\n", type);
c5c77ba1
JK
2730 dev->ieee80211_ptr->iftype = type;
2731 priv->wdev->iftype = type;
2732 nic->iftype = AP_MODE;
8a14330f 2733 PRINT_D(CORECONFIG_DBG, "priv->hWILCWFIDrv[%p]\n", priv->hWILCWFIDrv);
c5c77ba1 2734
c5c77ba1 2735 PRINT_D(HOSTAPD_DBG, "Downloading AP firmware\n");
65c8adcf 2736 linux_wlan_get_firmware(dev);
c5c77ba1 2737 /*If wilc is running, then close-open to actually get new firmware running (serves P2P)*/
299382cf 2738 if (wl->initialized) {
c5c77ba1 2739 nic->iftype = AP_MODE;
c5c77ba1
JK
2740 mac_close(dev);
2741 mac_open(dev);
2742
c5c77ba1
JK
2743 for (i = 0; i < num_reg_frame; i++) {
2744 PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", nic->g_struct_frame_reg[i].frame_type,
2745 nic->g_struct_frame_reg[i].reg);
2746 host_int_frame_register(priv->hWILCWFIDrv,
2747 nic->g_struct_frame_reg[i].frame_type,
2748 nic->g_struct_frame_reg[i].reg);
2749 }
2750 }
c5c77ba1
JK
2751 break;
2752
2753 case NL80211_IFTYPE_P2P_GO:
2754 PRINT_D(GENERIC_DBG, "start duringIP timer\n");
2755
72ed4dc7 2756 g_obtainingIP = true;
9eb06643 2757 mod_timer(&hDuringIpTimer, jiffies + msecs_to_jiffies(duringIP_TIME));
c5c77ba1 2758 host_int_set_power_mgmt(priv->hWILCWFIDrv, 0, 0);
c5c77ba1
JK
2759 /*Delete block ack has to be the latest config packet*/
2760 /*sent before downloading new FW. This is because it blocks on*/
2761 /*hWaitResponse semaphore, which allows previous config*/
2762 /*packets to actually take action on old FW*/
299382cf
GL
2763 host_int_del_All_Rx_BASession(priv->hWILCWFIDrv,
2764 wl->vif[0].bssid, TID);
72ed4dc7 2765 bEnablePS = false;
c5c77ba1 2766 PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_GO\n");
c5c77ba1
JK
2767 dev->ieee80211_ptr->iftype = type;
2768 priv->wdev->iftype = type;
2769
8a14330f 2770 PRINT_D(CORECONFIG_DBG, "priv->hWILCWFIDrv[%p]\n", priv->hWILCWFIDrv);
c5c77ba1 2771
c5c77ba1
JK
2772 PRINT_D(HOSTAPD_DBG, "Downloading P2P_CONCURRENCY_FIRMWARE\n");
2773
2774
c5c77ba1
JK
2775 nic->iftype = GO_MODE;
2776
2777 /* ensure that the message Q is empty */
2778 host_int_wait_msg_queue_idle();
53dc0cfe 2779 wilc1000_wlan_deinit(dev);
c5c77ba1
JK
2780 wilc1000_wlan_init(dev, nic);
2781 g_wilc_initialized = 1;
2782
2783
2784 /*Setting interface 1 drv handler and mac address in newly downloaded FW*/
299382cf
GL
2785 host_int_set_wfi_drv_handler(wl->vif[0].hif_drv);
2786 host_int_set_MacAddress(wl->vif[0].hif_drv,
2787 wl->vif[0].src_addr);
c5c77ba1
JK
2788 host_int_set_operation_mode(priv->hWILCWFIDrv, AP_MODE);
2789
2790 /*Add saved WEP keys, if any*/
2791 if (g_wep_keys_saved) {
df8b4830 2792 host_int_set_wep_default_key(wl->vif[0].hif_drv,
c5c77ba1 2793 g_key_wep_params.key_idx);
299382cf 2794 host_int_add_wep_key_bss_sta(wl->vif[0].hif_drv,
c5c77ba1
JK
2795 g_key_wep_params.key,
2796 g_key_wep_params.key_len,
2797 g_key_wep_params.key_idx);
2798 }
2799
2800 /*No matter the driver handler passed here, it will be overwriiten*/
2801 /*in Handle_FlushConnect() with gu8FlushedJoinReqDrvHandler*/
2802 host_int_flush_join_req(priv->hWILCWFIDrv);
2803
2804 /*Add saved PTK and GTK keys, if any*/
2805 if (g_ptk_keys_saved && g_gtk_keys_saved) {
2806 PRINT_D(CFG80211_DBG, "ptk %x %x %x cipher %x\n", g_key_ptk_params.key[0],
2807 g_key_ptk_params.key[1],
2808 g_key_ptk_params.key[2],
2809 g_key_ptk_params.cipher);
2810 PRINT_D(CFG80211_DBG, "gtk %x %x %x cipher %x\n", g_key_gtk_params.key[0],
2811 g_key_gtk_params.key[1],
2812 g_key_gtk_params.key[2],
2813 g_key_gtk_params.cipher);
299382cf
GL
2814 add_key(wl->vif[0].ndev->ieee80211_ptr->wiphy,
2815 wl->vif[0].ndev,
953d417a
CL
2816 g_add_ptk_key_params.key_idx,
2817 g_add_ptk_key_params.pairwise,
2818 g_add_ptk_key_params.mac_addr,
2819 (struct key_params *)(&g_key_ptk_params));
2820
299382cf
GL
2821 add_key(wl->vif[0].ndev->ieee80211_ptr->wiphy,
2822 wl->vif[0].ndev,
953d417a
CL
2823 g_add_gtk_key_params.key_idx,
2824 g_add_gtk_key_params.pairwise,
2825 g_add_gtk_key_params.mac_addr,
2826 (struct key_params *)(&g_key_gtk_params));
c5c77ba1 2827 }
c5c77ba1 2828
299382cf 2829 if (wl->initialized) {
c5c77ba1
JK
2830 for (i = 0; i < num_reg_frame; i++) {
2831 PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", nic->g_struct_frame_reg[i].frame_type,
2832 nic->g_struct_frame_reg[i].reg);
2833 host_int_frame_register(priv->hWILCWFIDrv,
2834 nic->g_struct_frame_reg[i].frame_type,
2835 nic->g_struct_frame_reg[i].reg);
2836 }
2837 }
c5c77ba1
JK
2838 break;
2839
2840 default:
2841 PRINT_ER("Unknown interface type= %d\n", type);
aaed3290 2842 return -EINVAL;
c5c77ba1
JK
2843 }
2844
aaed3290 2845 return 0;
c5c77ba1
JK
2846}
2847
c5c77ba1
JK
2848/* (austin.2013-07-23)
2849 *
2850 * To support revised cfg80211_ops
2851 *
2852 * add_beacon --> start_ap
2853 * set_beacon --> change_beacon
2854 * del_beacon --> stop_ap
2855 *
2856 * beacon_parameters --> cfg80211_ap_settings
2857 * cfg80211_beacon_data
2858 *
2859 * applicable for linux kernel 3.4+
2860 */
2861
2862/**
a13168d7 2863 * @brief start_ap
c5c77ba1
JK
2864 * @details Add a beacon with given parameters, @head, @interval
2865 * and @dtim_period will be valid, @tail is optional.
2866 * @param[in] wiphy
2867 * @param[in] dev The net device structure
2868 * @param[in] settings cfg80211_ap_settings parameters for the beacon to be added
2869 * @return int : Return 0 on Success.
2870 * @author austin
2871 * @date 23 JUL 2013
2872 * @version 1.0
2873 */
a13168d7
CL
2874static int start_ap(struct wiphy *wiphy, struct net_device *dev,
2875 struct cfg80211_ap_settings *settings)
c5c77ba1
JK
2876{
2877 struct cfg80211_beacon_data *beacon = &(settings->beacon);
2726887c 2878 struct wilc_priv *priv;
e6e12661 2879 s32 s32Error = 0;
684dc186
GL
2880 struct wilc *wl;
2881 perInterface_wlan_t *nic;
c5c77ba1
JK
2882
2883 priv = wiphy_priv(wiphy);
684dc186
GL
2884 nic = netdev_priv(dev);
2885 wl = nic->wilc;
c5c77ba1
JK
2886 PRINT_D(HOSTAPD_DBG, "Starting ap\n");
2887
17aacd43 2888 PRINT_D(HOSTAPD_DBG, "Interval = %d\n DTIM period = %d\n Head length = %zu Tail length = %zu\n",
c5c77ba1
JK
2889 settings->beacon_interval, settings->dtim_period, beacon->head_len, beacon->tail_len);
2890
80785a9a 2891 s32Error = set_channel(wiphy, &settings->chandef);
c5c77ba1 2892
e6e12661 2893 if (s32Error != 0)
c5c77ba1 2894 PRINT_ER("Error in setting channel\n");
c5c77ba1 2895
684dc186 2896 linux_wlan_set_bssid(dev, wl->vif[0].src_addr);
c5c77ba1 2897
c5c77ba1
JK
2898 s32Error = host_int_add_beacon(priv->hWILCWFIDrv,
2899 settings->beacon_interval,
2900 settings->dtim_period,
63d03e47
GKH
2901 beacon->head_len, (u8 *)beacon->head,
2902 beacon->tail_len, (u8 *)beacon->tail);
c5c77ba1
JK
2903
2904 return s32Error;
2905}
2906
2907/**
2a4c84d7 2908 * @brief change_beacon
c5c77ba1
JK
2909 * @details Add a beacon with given parameters, @head, @interval
2910 * and @dtim_period will be valid, @tail is optional.
2911 * @param[in] wiphy
2912 * @param[in] dev The net device structure
2913 * @param[in] beacon cfg80211_beacon_data for the beacon to be changed
2914 * @return int : Return 0 on Success.
2915 * @author austin
2916 * @date 23 JUL 2013
2917 * @version 1.0
2918 */
2a4c84d7
CL
2919static int change_beacon(struct wiphy *wiphy, struct net_device *dev,
2920 struct cfg80211_beacon_data *beacon)
c5c77ba1 2921{
2726887c 2922 struct wilc_priv *priv;
e6e12661 2923 s32 s32Error = 0;
c5c77ba1
JK
2924
2925 priv = wiphy_priv(wiphy);
2926 PRINT_D(HOSTAPD_DBG, "Setting beacon\n");
2927
2928
c5c77ba1
JK
2929 s32Error = host_int_add_beacon(priv->hWILCWFIDrv,
2930 0,
2931 0,
63d03e47
GKH
2932 beacon->head_len, (u8 *)beacon->head,
2933 beacon->tail_len, (u8 *)beacon->tail);
c5c77ba1
JK
2934
2935 return s32Error;
2936}
2937
2938/**
c8cddd79 2939 * @brief stop_ap
c5c77ba1
JK
2940 * @details Remove beacon configuration and stop sending the beacon.
2941 * @param[in]
2942 * @return int : Return 0 on Success.
2943 * @author austin
2944 * @date 23 JUL 2013
2945 * @version 1.0
2946 */
c8cddd79 2947static int stop_ap(struct wiphy *wiphy, struct net_device *dev)
c5c77ba1 2948{
e6e12661 2949 s32 s32Error = 0;
2726887c 2950 struct wilc_priv *priv;
63d03e47 2951 u8 NullBssid[ETH_ALEN] = {0};
c5c77ba1 2952
7ae43363
LK
2953 if (!wiphy)
2954 return -EFAULT;
c5c77ba1
JK
2955
2956 priv = wiphy_priv(wiphy);
2957
2958 PRINT_D(HOSTAPD_DBG, "Deleting beacon\n");
2959
c5c77ba1
JK
2960 linux_wlan_set_bssid(dev, NullBssid);
2961
c5c77ba1 2962 s32Error = host_int_del_beacon(priv->hWILCWFIDrv);
c5c77ba1 2963
7dc1d0cc
LK
2964 if (s32Error)
2965 PRINT_ER("Host delete beacon fail\n");
c5c77ba1 2966
c5c77ba1
JK
2967 return s32Error;
2968}
2969
c5c77ba1 2970/**
ed26955c 2971 * @brief add_station
c5c77ba1
JK
2972 * @details Add a new station.
2973 * @param[in]
2974 * @return int : Return 0 on Success.
2975 * @author mdaftedar
2976 * @date 01 MAR 2012
2977 * @version 1.0
2978 */
ed26955c
CL
2979static int add_station(struct wiphy *wiphy, struct net_device *dev,
2980 const u8 *mac, struct station_parameters *params)
c5c77ba1 2981{
e6e12661 2982 s32 s32Error = 0;
2726887c 2983 struct wilc_priv *priv;
6a89ba9c 2984 struct add_sta_param strStaParams = { {0} };
c5c77ba1
JK
2985 perInterface_wlan_t *nic;
2986
7ae43363
LK
2987 if (!wiphy)
2988 return -EFAULT;
c5c77ba1
JK
2989
2990 priv = wiphy_priv(wiphy);
2991 nic = netdev_priv(dev);
2992
2993 if (nic->iftype == AP_MODE || nic->iftype == GO_MODE) {
2353c388 2994 memcpy(strStaParams.bssid, mac, ETH_ALEN);
d00d2ba3 2995 memcpy(priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid], mac, ETH_ALEN);
4101eb8a 2996 strStaParams.aid = params->aid;
e734223c 2997 strStaParams.rates_len = params->supported_rates_len;
a622e016 2998 strStaParams.rates = params->supported_rates;
c5c77ba1
JK
2999
3000 PRINT_D(CFG80211_DBG, "Adding station parameters %d\n", params->aid);
3001
3002 PRINT_D(CFG80211_DBG, "BSSID = %x%x%x%x%x%x\n", priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][0], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][1], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][2], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][3], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][4],
3003 priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][5]);
4101eb8a 3004 PRINT_D(HOSTAPD_DBG, "ASSOC ID = %d\n", strStaParams.aid);
e734223c
LK
3005 PRINT_D(HOSTAPD_DBG, "Number of supported rates = %d\n",
3006 strStaParams.rates_len);
c5c77ba1 3007
b1413b60 3008 if (params->ht_capa == NULL) {
22520120 3009 strStaParams.ht_supported = false;
c5c77ba1 3010 } else {
22520120 3011 strStaParams.ht_supported = true;
0d073f69 3012 strStaParams.ht_capa_info = params->ht_capa->cap_info;
fba1f2d2 3013 strStaParams.ht_ampdu_params = params->ht_capa->ampdu_params_info;
5ebbf4f7
LK
3014 memcpy(strStaParams.ht_supp_mcs_set,
3015 &params->ht_capa->mcs,
3016 WILC_SUPP_MCS_SET_SIZE);
223741d7 3017 strStaParams.ht_ext_params = params->ht_capa->extended_ht_cap_info;
74fe73cf 3018 strStaParams.ht_tx_bf_cap = params->ht_capa->tx_BF_cap_info;
a486baff 3019 strStaParams.ht_ante_sel = params->ht_capa->antenna_selection_info;
c5c77ba1
JK
3020 }
3021
f676e17a 3022 strStaParams.flags_mask = params->sta_flags_mask;
67ab64e4 3023 strStaParams.flags_set = params->sta_flags_set;
c5c77ba1 3024
22520120
LK
3025 PRINT_D(HOSTAPD_DBG, "IS HT supported = %d\n",
3026 strStaParams.ht_supported);
0d073f69
LK
3027 PRINT_D(HOSTAPD_DBG, "Capability Info = %d\n",
3028 strStaParams.ht_capa_info);
fba1f2d2
LK
3029 PRINT_D(HOSTAPD_DBG, "AMPDU Params = %d\n",
3030 strStaParams.ht_ampdu_params);
223741d7
LK
3031 PRINT_D(HOSTAPD_DBG, "HT Extended params = %d\n",
3032 strStaParams.ht_ext_params);
74fe73cf
LK
3033 PRINT_D(HOSTAPD_DBG, "Tx Beamforming Cap = %d\n",
3034 strStaParams.ht_tx_bf_cap);
a486baff
LK
3035 PRINT_D(HOSTAPD_DBG, "Antenna selection info = %d\n",
3036 strStaParams.ht_ante_sel);
f676e17a
LK
3037 PRINT_D(HOSTAPD_DBG, "Flag Mask = %d\n",
3038 strStaParams.flags_mask);
67ab64e4
LK
3039 PRINT_D(HOSTAPD_DBG, "Flag Set = %d\n",
3040 strStaParams.flags_set);
c5c77ba1
JK
3041
3042 s32Error = host_int_add_station(priv->hWILCWFIDrv, &strStaParams);
7dc1d0cc
LK
3043 if (s32Error)
3044 PRINT_ER("Host add station fail\n");
c5c77ba1
JK
3045 }
3046
c5c77ba1
JK
3047 return s32Error;
3048}
3049
3050/**
a0a8be95 3051 * @brief del_station
c5c77ba1
JK
3052 * @details Remove a station; @mac may be NULL to remove all stations.
3053 * @param[in]
3054 * @return int : Return 0 on Success.
3055 * @author mdaftedar
3056 * @date 01 MAR 2012
3057 * @version 1.0
3058 */
a0a8be95
CL
3059static int del_station(struct wiphy *wiphy, struct net_device *dev,
3060 struct station_del_parameters *params)
c5c77ba1 3061{
057d1e97 3062 const u8 *mac = params->mac;
e6e12661 3063 s32 s32Error = 0;
2726887c 3064 struct wilc_priv *priv;
c5c77ba1 3065 perInterface_wlan_t *nic;
8dfaafd6 3066
7ae43363
LK
3067 if (!wiphy)
3068 return -EFAULT;
c5c77ba1
JK
3069
3070 priv = wiphy_priv(wiphy);
3071 nic = netdev_priv(dev);
3072
3073 if (nic->iftype == AP_MODE || nic->iftype == GO_MODE) {
3074 PRINT_D(HOSTAPD_DBG, "Deleting station\n");
3075
3076
b1413b60 3077 if (mac == NULL) {
17aacd43 3078 PRINT_D(HOSTAPD_DBG, "All associated stations\n");
c5c77ba1
JK
3079 s32Error = host_int_del_allstation(priv->hWILCWFIDrv, priv->assoc_stainfo.au8Sta_AssociatedBss);
3080 } else {
3081 PRINT_D(HOSTAPD_DBG, "With mac address: %x%x%x%x%x%x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
3082 }
3083
c5c77ba1 3084 s32Error = host_int_del_station(priv->hWILCWFIDrv, mac);
c5c77ba1 3085
7dc1d0cc
LK
3086 if (s32Error)
3087 PRINT_ER("Host delete station fail\n");
c5c77ba1
JK
3088 }
3089 return s32Error;
3090}
3091
3092/**
14b42084 3093 * @brief change_station
c5c77ba1
JK
3094 * @details Modify a given station.
3095 * @param[in]
3096 * @return int : Return 0 on Success.
3097 * @author mdaftedar
3098 * @date 01 MAR 2012
3099 * @version 1.0
3100 */
14b42084
CL
3101static int change_station(struct wiphy *wiphy, struct net_device *dev,
3102 const u8 *mac, struct station_parameters *params)
c5c77ba1 3103{
e6e12661 3104 s32 s32Error = 0;
2726887c 3105 struct wilc_priv *priv;
6a89ba9c 3106 struct add_sta_param strStaParams = { {0} };
c5c77ba1
JK
3107 perInterface_wlan_t *nic;
3108
3109
3110 PRINT_D(HOSTAPD_DBG, "Change station paramters\n");
3111
7ae43363
LK
3112 if (!wiphy)
3113 return -EFAULT;
c5c77ba1
JK
3114
3115 priv = wiphy_priv(wiphy);
3116 nic = netdev_priv(dev);
3117
3118 if (nic->iftype == AP_MODE || nic->iftype == GO_MODE) {
2353c388 3119 memcpy(strStaParams.bssid, mac, ETH_ALEN);
4101eb8a 3120 strStaParams.aid = params->aid;
e734223c 3121 strStaParams.rates_len = params->supported_rates_len;
a622e016 3122 strStaParams.rates = params->supported_rates;
c5c77ba1 3123
2353c388
LK
3124 PRINT_D(HOSTAPD_DBG, "BSSID = %x%x%x%x%x%x\n",
3125 strStaParams.bssid[0], strStaParams.bssid[1],
3126 strStaParams.bssid[2], strStaParams.bssid[3],
3127 strStaParams.bssid[4], strStaParams.bssid[5]);
4101eb8a 3128 PRINT_D(HOSTAPD_DBG, "ASSOC ID = %d\n", strStaParams.aid);
e734223c
LK
3129 PRINT_D(HOSTAPD_DBG, "Number of supported rates = %d\n",
3130 strStaParams.rates_len);
c5c77ba1 3131
b1413b60 3132 if (params->ht_capa == NULL) {
22520120 3133 strStaParams.ht_supported = false;
c5c77ba1 3134 } else {
22520120 3135 strStaParams.ht_supported = true;
0d073f69 3136 strStaParams.ht_capa_info = params->ht_capa->cap_info;
fba1f2d2 3137 strStaParams.ht_ampdu_params = params->ht_capa->ampdu_params_info;
5ebbf4f7
LK
3138 memcpy(strStaParams.ht_supp_mcs_set,
3139 &params->ht_capa->mcs,
3140 WILC_SUPP_MCS_SET_SIZE);
223741d7 3141 strStaParams.ht_ext_params = params->ht_capa->extended_ht_cap_info;
74fe73cf 3142 strStaParams.ht_tx_bf_cap = params->ht_capa->tx_BF_cap_info;
a486baff 3143 strStaParams.ht_ante_sel = params->ht_capa->antenna_selection_info;
c5c77ba1
JK
3144 }
3145
f676e17a 3146 strStaParams.flags_mask = params->sta_flags_mask;
67ab64e4 3147 strStaParams.flags_set = params->sta_flags_set;
c5c77ba1 3148
22520120
LK
3149 PRINT_D(HOSTAPD_DBG, "IS HT supported = %d\n",
3150 strStaParams.ht_supported);
0d073f69
LK
3151 PRINT_D(HOSTAPD_DBG, "Capability Info = %d\n",
3152 strStaParams.ht_capa_info);
fba1f2d2
LK
3153 PRINT_D(HOSTAPD_DBG, "AMPDU Params = %d\n",
3154 strStaParams.ht_ampdu_params);
223741d7
LK
3155 PRINT_D(HOSTAPD_DBG, "HT Extended params = %d\n",
3156 strStaParams.ht_ext_params);
74fe73cf
LK
3157 PRINT_D(HOSTAPD_DBG, "Tx Beamforming Cap = %d\n",
3158 strStaParams.ht_tx_bf_cap);
a486baff
LK
3159 PRINT_D(HOSTAPD_DBG, "Antenna selection info = %d\n",
3160 strStaParams.ht_ante_sel);
f676e17a
LK
3161 PRINT_D(HOSTAPD_DBG, "Flag Mask = %d\n",
3162 strStaParams.flags_mask);
67ab64e4
LK
3163 PRINT_D(HOSTAPD_DBG, "Flag Set = %d\n",
3164 strStaParams.flags_set);
c5c77ba1
JK
3165
3166 s32Error = host_int_edit_station(priv->hWILCWFIDrv, &strStaParams);
7dc1d0cc
LK
3167 if (s32Error)
3168 PRINT_ER("Host edit station fail\n");
c5c77ba1
JK
3169 }
3170 return s32Error;
3171}
3172
3173
3174/**
69deb4c2 3175 * @brief add_virtual_intf
c5c77ba1
JK
3176 * @details
3177 * @param[in]
3178 * @return int : Return 0 on Success.
3179 * @author mdaftedar
3180 * @date 01 JUL 2012
3181 * @version 1.0
3182 */
37316e81
CL
3183static struct wireless_dev *add_virtual_intf(struct wiphy *wiphy,
3184 const char *name,
3185 unsigned char name_assign_type,
3186 enum nl80211_iftype type,
3187 u32 *flags,
3188 struct vif_params *params)
c5c77ba1
JK
3189{
3190 perInterface_wlan_t *nic;
2726887c 3191 struct wilc_priv *priv;
c5c77ba1 3192 struct net_device *new_ifc = NULL;
8dfaafd6 3193
c5c77ba1
JK
3194 priv = wiphy_priv(wiphy);
3195
3196
3197
3198 PRINT_D(HOSTAPD_DBG, "Adding monitor interface[%p]\n", priv->wdev->netdev);
3199
3200 nic = netdev_priv(priv->wdev->netdev);
3201
3202
3203 if (type == NL80211_IFTYPE_MONITOR) {
3204 PRINT_D(HOSTAPD_DBG, "Monitor interface mode: Initializing mon interface virtual device driver\n");
3205 PRINT_D(HOSTAPD_DBG, "Adding monitor interface[%p]\n", nic->wilc_netdev);
3206 new_ifc = WILC_WFI_init_mon_interface(name, nic->wilc_netdev);
3207 if (new_ifc != NULL) {
3208 PRINT_D(HOSTAPD_DBG, "Setting monitor flag in private structure\n");
c5c77ba1
JK
3209 nic = netdev_priv(priv->wdev->netdev);
3210 nic->monitor_flag = 1;
c5c77ba1
JK
3211 } else
3212 PRINT_ER("Error in initializing monitor interface\n ");
3213 }
c5c77ba1 3214 return priv->wdev;
c5c77ba1
JK
3215}
3216
3217/**
b4a73355 3218 * @brief del_virtual_intf
c5c77ba1
JK
3219 * @details
3220 * @param[in]
3221 * @return int : Return 0 on Success.
3222 * @author mdaftedar
3223 * @date 01 JUL 2012
3224 * @version 1.0
3225 */
956d7211 3226static int del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
c5c77ba1
JK
3227{
3228 PRINT_D(HOSTAPD_DBG, "Deleting virtual interface\n");
e6e12661 3229 return 0;
c5c77ba1
JK
3230}
3231
08241924 3232static struct cfg80211_ops wilc_cfg80211_ops = {
c5c77ba1 3233
80785a9a 3234 .set_monitor_channel = set_channel,
0e30d06d 3235 .scan = scan,
4ffbcdb6 3236 .connect = connect,
b027cde9 3237 .disconnect = disconnect,
953d417a 3238 .add_key = add_key,
3044ba7e 3239 .del_key = del_key,
f4893dfc 3240 .get_key = get_key,
0f5b8ca3 3241 .set_default_key = set_default_key,
69deb4c2 3242 .add_virtual_intf = add_virtual_intf,
b4a73355 3243 .del_virtual_intf = del_virtual_intf,
3615e9a3 3244 .change_virtual_intf = change_virtual_intf,
c5c77ba1 3245
a13168d7 3246 .start_ap = start_ap,
2a4c84d7 3247 .change_beacon = change_beacon,
c8cddd79 3248 .stop_ap = stop_ap,
ed26955c 3249 .add_station = add_station,
a0a8be95 3250 .del_station = del_station,
14b42084 3251 .change_station = change_station,
f06f562d 3252 .get_station = get_station,
bdb6338f 3253 .dump_station = dump_station,
a5f7db6a 3254 .change_bss = change_bss,
a76b63ef 3255 .set_wiphy_params = set_wiphy_params,
c5c77ba1 3256
4d46657a 3257 .set_pmksa = set_pmksa,
1ff86d96 3258 .del_pmksa = del_pmksa,
b33c39b1 3259 .flush_pmksa = flush_pmksa,
6d19d695 3260 .remain_on_channel = remain_on_channel,
1dd5440b 3261 .cancel_remain_on_channel = cancel_remain_on_channel,
4a2f9b38 3262 .mgmt_tx_cancel_wait = mgmt_tx_cancel_wait,
12a26a33 3263 .mgmt_tx = mgmt_tx,
8e0735c5 3264 .mgmt_frame_register = wilc_mgmt_frame_register,
46530679 3265 .set_power_mgmt = set_power_mgmt,
a8047e26 3266 .set_cqm_rssi_config = set_cqm_rssi_config,
c5c77ba1
JK
3267
3268};
3269
3270
3271
3272
3273
3274/**
3275 * @brief WILC_WFI_update_stats
3276 * @details Modify parameters for a given BSS.
3277 * @param[in]
3278 * @return int : Return 0 on Success.
3279 * @author mdaftedar
3280 * @date 01 MAR 2012
cdc9cba5 3281 * @version 1.0
c5c77ba1
JK
3282 */
3283int WILC_WFI_update_stats(struct wiphy *wiphy, u32 pktlen, u8 changed)
3284{
3285
2726887c 3286 struct wilc_priv *priv;
c5c77ba1
JK
3287
3288 priv = wiphy_priv(wiphy);
c5c77ba1
JK
3289 switch (changed) {
3290
3291 case WILC_WFI_RX_PKT:
3292 {
c5c77ba1
JK
3293 priv->netstats.rx_packets++;
3294 priv->netstats.rx_bytes += pktlen;
3295 priv->netstats.rx_time = get_jiffies_64();
3296 }
3297 break;
3298
3299 case WILC_WFI_TX_PKT:
3300 {
3301 priv->netstats.tx_packets++;
3302 priv->netstats.tx_bytes += pktlen;
3303 priv->netstats.tx_time = get_jiffies_64();
3304
3305 }
3306 break;
3307
3308 default:
3309 break;
3310 }
c5c77ba1
JK
3311 return 0;
3312}
c5c77ba1 3313
c5c77ba1
JK
3314/**
3315 * @brief WILC_WFI_CfgAlloc
3316 * @details Allocation of the wireless device structure and assigning it
3317 * to the cfg80211 operations structure.
3318 * @param[in] NONE
3319 * @return wireless_dev : Returns pointer to wireless_dev structure.
3320 * @author mdaftedar
3321 * @date 01 MAR 2012
3322 * @version 1.0
3323 */
3324struct wireless_dev *WILC_WFI_CfgAlloc(void)
3325{
3326
3327 struct wireless_dev *wdev;
3328
3329
3330 PRINT_D(CFG80211_DBG, "Allocating wireless device\n");
3331 /*Allocating the wireless device structure*/
3332 wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
3333 if (!wdev) {
3334 PRINT_ER("Cannot allocate wireless device\n");
3335 goto _fail_;
3336 }
3337
3338 /*Creating a new wiphy, linking wireless structure with the wiphy structure*/
2726887c 3339 wdev->wiphy = wiphy_new(&wilc_cfg80211_ops, sizeof(struct wilc_priv));
c5c77ba1
JK
3340 if (!wdev->wiphy) {
3341 PRINT_ER("Cannot allocate wiphy\n");
3342 goto _fail_mem_;
3343
3344 }
3345
c5c77ba1
JK
3346 /* enable 802.11n HT */
3347 WILC_WFI_band_2ghz.ht_cap.ht_supported = 1;
3348 WILC_WFI_band_2ghz.ht_cap.cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
3349 WILC_WFI_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
3350 WILC_WFI_band_2ghz.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K;
3351 WILC_WFI_band_2ghz.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
c5c77ba1
JK
3352
3353 /*wiphy bands*/
3354 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &WILC_WFI_band_2ghz;
3355
3356 return wdev;
3357
3358_fail_mem_:
3359 kfree(wdev);
3360_fail_:
3361 return NULL;
3362
3363}
3364/**
8459fd54 3365 * @brief wilc_create_wiphy
c5c77ba1
JK
3366 * @details Registering of the wiphy structure and interface modes
3367 * @param[in] NONE
3368 * @return NONE
3369 * @author mdaftedar
3370 * @date 01 MAR 2012
3371 * @version 1.0
3372 */
8459fd54 3373struct wireless_dev *wilc_create_wiphy(struct net_device *net)
c5c77ba1 3374{
2726887c 3375 struct wilc_priv *priv;
c5c77ba1 3376 struct wireless_dev *wdev;
e6e12661 3377 s32 s32Error = 0;
c5c77ba1
JK
3378
3379 PRINT_D(CFG80211_DBG, "Registering wifi device\n");
3380
3381 wdev = WILC_WFI_CfgAlloc();
3382 if (wdev == NULL) {
3383 PRINT_ER("CfgAlloc Failed\n");
3384 return NULL;
3385 }
3386
3387
3388 /*Return hardware description structure (wiphy)'s priv*/
3389 priv = wdev_priv(wdev);
83383ea3 3390 sema_init(&(priv->SemHandleUpdateStats), 1);
c5c77ba1
JK
3391
3392 /*Link the wiphy with wireless structure*/
3393 priv->wdev = wdev;
3394
3395 /*Maximum number of probed ssid to be added by user for the scan request*/
3396 wdev->wiphy->max_scan_ssids = MAX_NUM_PROBED_SSID;
c5c77ba1
JK
3397 /*Maximum number of pmkids to be cashed*/
3398 wdev->wiphy->max_num_pmkids = WILC_MAX_NUM_PMKIDS;
3399 PRINT_INFO(CFG80211_DBG, "Max number of PMKIDs = %d\n", wdev->wiphy->max_num_pmkids);
c5c77ba1
JK
3400
3401 wdev->wiphy->max_scan_ie_len = 1000;
3402
3403 /*signal strength in mBm (100*dBm) */
3404 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
3405
3406 /*Set the availaible cipher suites*/
3407 wdev->wiphy->cipher_suites = cipher_suites;
3408 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
c5c77ba1
JK
3409 /*Setting default managment types: for register action frame: */
3410 wdev->wiphy->mgmt_stypes = wilc_wfi_cfg80211_mgmt_types;
c5c77ba1 3411
c5c77ba1
JK
3412 wdev->wiphy->max_remain_on_channel_duration = 500;
3413 /*Setting the wiphy interfcae mode and type before registering the wiphy*/
3414 wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR) | BIT(NL80211_IFTYPE_P2P_GO) |
3415 BIT(NL80211_IFTYPE_P2P_CLIENT);
c5c77ba1 3416 wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
c5c77ba1
JK
3417 wdev->iftype = NL80211_IFTYPE_STATION;
3418
3419
3420
3421 PRINT_INFO(CFG80211_DBG, "Max scan ids = %d,Max scan IE len = %d,Signal Type = %d,Interface Modes = %d,Interface Type = %d\n",
3422 wdev->wiphy->max_scan_ssids, wdev->wiphy->max_scan_ie_len, wdev->wiphy->signal_type,
3423 wdev->wiphy->interface_modes, wdev->iftype);
3424
3425 #ifdef WILC_SDIO
cdc9cba5 3426 set_wiphy_dev(wdev->wiphy, &local_sdio_func->dev);
c5c77ba1
JK
3427 #endif
3428
3429 /*Register wiphy structure*/
3430 s32Error = wiphy_register(wdev->wiphy);
3431 if (s32Error) {
3432 PRINT_ER("Cannot register wiphy device\n");
3433 /*should define what action to be taken in such failure*/
3434 } else {
3435 PRINT_D(CFG80211_DBG, "Successful Registering\n");
3436 }
3437
c5c77ba1 3438 priv->dev = net;
c5c77ba1
JK
3439 return wdev;
3440
3441
3442}
3443/**
3444 * @brief WILC_WFI_WiphyFree
3445 * @details Freeing allocation of the wireless device structure
3446 * @param[in] NONE
3447 * @return NONE
3448 * @author mdaftedar
3449 * @date 01 MAR 2012
3450 * @version 1.0
3451 */
dd4b6a83 3452int wilc_init_host_int(struct net_device *net)
c5c77ba1
JK
3453{
3454
1a8ccd85 3455 int s32Error = 0;
c5c77ba1 3456
2726887c 3457 struct wilc_priv *priv;
c5c77ba1 3458
c5c77ba1
JK
3459 PRINT_D(INIT_DBG, "Host[%p][%p]\n", net, net->ieee80211_ptr);
3460 priv = wdev_priv(net->ieee80211_ptr);
3461 if (op_ifcs == 0) {
93dee8ee 3462 setup_timer(&hAgingTimer, remove_network_from_shadow, 0);
93dee8ee 3463 setup_timer(&hDuringIpTimer, clear_duringIP, 0);
c5c77ba1
JK
3464 }
3465 op_ifcs++;
3466 if (s32Error < 0) {
3467 PRINT_ER("Failed to creat refresh Timer\n");
3468 return s32Error;
3469 }
3470
72ed4dc7 3471 priv->gbAutoRateAdjusted = false;
c5c77ba1 3472
72ed4dc7 3473 priv->bInP2PlistenState = false;
c5c77ba1 3474
83383ea3 3475 sema_init(&(priv->hSemScanReq), 1);
d5382219 3476 s32Error = host_int_init(net, &priv->hWILCWFIDrv);
f1fe9c43 3477 if (s32Error)
c5c77ba1 3478 PRINT_ER("Error while initializing hostinterface\n");
f1fe9c43 3479
c5c77ba1
JK
3480 return s32Error;
3481}
3482
3483/**
3484 * @brief WILC_WFI_WiphyFree
3485 * @details Freeing allocation of the wireless device structure
3486 * @param[in] NONE
3487 * @return NONE
3488 * @author mdaftedar
3489 * @date 01 MAR 2012
3490 * @version 1.0
3491 */
a9a16823 3492int wilc_deinit_host_int(struct net_device *net)
c5c77ba1 3493{
1a8ccd85 3494 int s32Error = 0;
c5c77ba1 3495
2726887c 3496 struct wilc_priv *priv;
8dfaafd6 3497
c5c77ba1
JK
3498 priv = wdev_priv(net->ieee80211_ptr);
3499
72ed4dc7 3500 priv->gbAutoRateAdjusted = false;
c5c77ba1 3501
72ed4dc7 3502 priv->bInP2PlistenState = false;
c5c77ba1
JK
3503
3504 op_ifcs--;
3505
3506 s32Error = host_int_deinit(priv->hWILCWFIDrv);
c5c77ba1
JK
3507
3508 /* Clear the Shadow scan */
3509 clear_shadow_scan(priv);
c5c77ba1
JK
3510 if (op_ifcs == 0) {
3511 PRINT_D(CORECONFIG_DBG, "destroy during ip\n");
4183e979 3512 del_timer_sync(&hDuringIpTimer);
c5c77ba1 3513 }
c5c77ba1 3514
f1fe9c43 3515 if (s32Error)
c5c77ba1 3516 PRINT_ER("Error while deintializing host interface\n");
f1fe9c43 3517
c5c77ba1
JK
3518 return s32Error;
3519}
3520
3521
3522/**
3523 * @brief WILC_WFI_WiphyFree
3524 * @details Freeing allocation of the wireless device structure
3525 * @param[in] NONE
3526 * @return NONE
3527 * @author mdaftedar
3528 * @date 01 MAR 2012
3529 * @version 1.0
3530 */
96da20a9 3531void wilc_free_wiphy(struct net_device *net)
c5c77ba1 3532{
c5c77ba1
JK
3533 PRINT_D(CFG80211_DBG, "Unregistering wiphy\n");
3534
619837ae 3535 if (!net) {
c5c77ba1
JK
3536 PRINT_D(INIT_DBG, "net_device is NULL\n");
3537 return;
3538 }
3539
619837ae 3540 if (!net->ieee80211_ptr) {
c5c77ba1
JK
3541 PRINT_D(INIT_DBG, "ieee80211_ptr is NULL\n");
3542 return;
3543 }
3544
619837ae 3545 if (!net->ieee80211_ptr->wiphy) {
c5c77ba1
JK
3546 PRINT_D(INIT_DBG, "wiphy is NULL\n");
3547 return;
3548 }
3549
3550 wiphy_unregister(net->ieee80211_ptr->wiphy);
3551
3552 PRINT_D(INIT_DBG, "Freeing wiphy\n");
3553 wiphy_free(net->ieee80211_ptr->wiphy);
3554 kfree(net->ieee80211_ptr);
c5c77ba1 3555}
This page took 0.610505 seconds and 5 git commands to generate.