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