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