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