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