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