2 * @file wilc_wfi_cfgopertaions.c
3 * @brief CFG80211 Function Implementation functionality
8 * @sa wilc_wfi_cfgopertaions.h top level OS wrapper file
13 #include "wilc_wfi_cfgoperations.h"
14 #include "wilc_wlan.c"
16 #include "linux_wlan_sdio.h" /* tony : for set_wiphy_dev() */
20 #define IS_MANAGMEMENT 0x100
21 #define IS_MANAGMEMENT_CALLBACK 0x080
22 #define IS_MGMT_STATUS_SUCCES 0x040
23 #define GET_PKT_OFFSET(a) (((a) >> 22) & 0x1ff)
25 extern int linux_wlan_get_firmware(perInterface_wlan_t *p_nic);
26 extern u16 Set_machw_change_vir_if(bool bValue);
28 extern int mac_open(struct net_device *ndev);
29 extern int mac_close(struct net_device *ndev);
31 tstrNetworkInfo astrLastScannedNtwrksShadow[MAX_NUM_SCANNED_NETWORKS_SHADOW];
32 u32 u32LastScannedNtwrksCountShadow;
33 #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
34 struct timer_list hDuringIpTimer;
36 struct timer_list hAgingTimer;
38 extern u8 u8ConnectedSSID[6];
41 u8 g_wilc_initialized = 1;
42 extern linux_wlan_t *g_linux_wlan;
43 #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
44 extern bool g_obtainingIP;
47 #define CHAN2G(_channel, _freq, _flags) { \
48 .band = IEEE80211_BAND_2GHZ, \
49 .center_freq = (_freq), \
50 .hw_value = (_channel), \
52 .max_antenna_gain = 0, \
56 /*Frequency range for channels*/
57 static struct ieee80211_channel WILC_WFI_2ghz_channels[] = {
74 #define RATETAB_ENT(_rate, _hw_value, _flags) { \
76 .hw_value = (_hw_value), \
81 /* Table 6 in section 3.2.1.1 */
82 static struct ieee80211_rate WILC_WFI_rates[] = {
83 RATETAB_ENT(10, 0, 0),
84 RATETAB_ENT(20, 1, 0),
85 RATETAB_ENT(55, 2, 0),
86 RATETAB_ENT(110, 3, 0),
87 RATETAB_ENT(60, 9, 0),
88 RATETAB_ENT(90, 6, 0),
89 RATETAB_ENT(120, 7, 0),
90 RATETAB_ENT(180, 8, 0),
91 RATETAB_ENT(240, 9, 0),
92 RATETAB_ENT(360, 10, 0),
93 RATETAB_ENT(480, 11, 0),
94 RATETAB_ENT(540, 12, 0),
98 struct p2p_mgmt_data {
103 /*Global variable used to state the current connected STA channel*/
104 u8 u8WLANChannel = INVALID_CHANNEL;
109 u8 u8P2P_oui[] = {0x50, 0x6f, 0x9A, 0x09};
110 u8 u8P2Plocalrandom = 0x01;
111 u8 u8P2Precvrandom = 0x00;
112 u8 u8P2P_vendorspec[] = {0xdd, 0x05, 0x00, 0x08, 0x40, 0x03};
116 static struct ieee80211_supported_band WILC_WFI_band_2ghz = {
117 .channels = WILC_WFI_2ghz_channels,
118 .n_channels = ARRAY_SIZE(WILC_WFI_2ghz_channels),
119 .bitrates = WILC_WFI_rates,
120 .n_bitrates = ARRAY_SIZE(WILC_WFI_rates),
125 struct add_key_params {
130 struct add_key_params g_add_gtk_key_params;
131 struct wilc_wfi_key g_key_gtk_params;
132 struct add_key_params g_add_ptk_key_params;
133 struct wilc_wfi_key g_key_ptk_params;
134 struct wilc_wfi_wep_key g_key_wep_params;
135 bool g_ptk_keys_saved;
136 bool g_gtk_keys_saved;
137 bool g_wep_keys_saved;
139 #define AGING_TIME (9 * 1000)
140 #define duringIP_TIME 15000
142 void clear_shadow_scan(void *pUserVoid)
147 del_timer_sync(&hAgingTimer);
148 PRINT_INFO(CORECONFIG_DBG, "destroy aging timer\n");
150 for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
151 if (astrLastScannedNtwrksShadow[u32LastScannedNtwrksCountShadow].pu8IEs != NULL) {
152 kfree(astrLastScannedNtwrksShadow[i].pu8IEs);
153 astrLastScannedNtwrksShadow[u32LastScannedNtwrksCountShadow].pu8IEs = NULL;
156 host_int_freeJoinParams(astrLastScannedNtwrksShadow[i].pJoinParams);
157 astrLastScannedNtwrksShadow[i].pJoinParams = NULL;
159 u32LastScannedNtwrksCountShadow = 0;
164 u32 get_rssi_avg(tstrNetworkInfo *pstrNetworkInfo)
168 u8 num_rssi = (pstrNetworkInfo->strRssi.u8Full) ? NUM_RSSI : (pstrNetworkInfo->strRssi.u8Index);
170 for (i = 0; i < num_rssi; i++)
171 rssi_v += pstrNetworkInfo->strRssi.as8RSSI[i];
177 void refresh_scan(void *pUserVoid, u8 all, bool bDirectScan)
179 struct wilc_priv *priv;
181 struct cfg80211_bss *bss = NULL;
185 priv = (struct wilc_priv *)pUserVoid;
186 wiphy = priv->dev->ieee80211_ptr->wiphy;
188 for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
189 tstrNetworkInfo *pstrNetworkInfo;
191 pstrNetworkInfo = &(astrLastScannedNtwrksShadow[i]);
194 if ((!pstrNetworkInfo->u8Found) || all) {
196 struct ieee80211_channel *channel;
198 if (pstrNetworkInfo != NULL) {
200 s32Freq = ieee80211_channel_to_frequency((s32)pstrNetworkInfo->u8channel, IEEE80211_BAND_2GHZ);
201 channel = ieee80211_get_channel(wiphy, s32Freq);
203 rssi = get_rssi_avg(pstrNetworkInfo);
204 if (memcmp("DIRECT-", pstrNetworkInfo->au8ssid, 7) || bDirectScan) {
205 bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, pstrNetworkInfo->au8bssid, pstrNetworkInfo->u64Tsf, pstrNetworkInfo->u16CapInfo,
206 pstrNetworkInfo->u16BeaconPeriod, (const u8 *)pstrNetworkInfo->pu8IEs,
207 (size_t)pstrNetworkInfo->u16IEsLen, (((s32)rssi) * 100), GFP_KERNEL);
208 cfg80211_put_bss(wiphy, bss);
217 void reset_shadow_found(void *pUserVoid)
221 for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
222 astrLastScannedNtwrksShadow[i].u8Found = 0;
227 void update_scan_time(void *pUserVoid)
231 for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
232 astrLastScannedNtwrksShadow[i].u32TimeRcvdInScan = jiffies;
236 static void remove_network_from_shadow(unsigned long arg)
238 unsigned long now = jiffies;
242 for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
243 if (time_after(now, astrLastScannedNtwrksShadow[i].u32TimeRcvdInScan + (unsigned long)(SCAN_RESULT_EXPIRE))) {
244 PRINT_D(CFG80211_DBG, "Network expired in ScanShadow: %s\n", astrLastScannedNtwrksShadow[i].au8ssid);
246 if (astrLastScannedNtwrksShadow[i].pu8IEs != NULL) {
247 kfree(astrLastScannedNtwrksShadow[i].pu8IEs);
248 astrLastScannedNtwrksShadow[i].pu8IEs = NULL;
251 host_int_freeJoinParams(astrLastScannedNtwrksShadow[i].pJoinParams);
253 for (j = i; (j < u32LastScannedNtwrksCountShadow - 1); j++) {
254 astrLastScannedNtwrksShadow[j] = astrLastScannedNtwrksShadow[j + 1];
256 u32LastScannedNtwrksCountShadow--;
260 PRINT_D(CFG80211_DBG, "Number of cached networks: %d\n", u32LastScannedNtwrksCountShadow);
261 if (u32LastScannedNtwrksCountShadow != 0) {
262 hAgingTimer.data = arg;
263 mod_timer(&hAgingTimer, jiffies + msecs_to_jiffies(AGING_TIME));
265 PRINT_D(CFG80211_DBG, "No need to restart Aging timer\n");
269 #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
270 static void clear_duringIP(unsigned long arg)
272 PRINT_D(GENERIC_DBG, "GO:IP Obtained , enable scan\n");
273 g_obtainingIP = false;
277 int8_t is_network_in_shadow(tstrNetworkInfo *pstrNetworkInfo, void *pUserVoid)
282 if (u32LastScannedNtwrksCountShadow == 0) {
283 PRINT_D(CFG80211_DBG, "Starting Aging timer\n");
284 hAgingTimer.data = (unsigned long)pUserVoid;
285 mod_timer(&hAgingTimer, jiffies + msecs_to_jiffies(AGING_TIME));
288 /* Linear search for now */
289 for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
290 if (memcmp(astrLastScannedNtwrksShadow[i].au8bssid,
291 pstrNetworkInfo->au8bssid, 6) == 0) {
300 void add_network_to_shadow(tstrNetworkInfo *pstrNetworkInfo, void *pUserVoid, void *pJoinParams)
302 int8_t ap_found = is_network_in_shadow(pstrNetworkInfo, pUserVoid);
306 if (u32LastScannedNtwrksCountShadow >= MAX_NUM_SCANNED_NETWORKS_SHADOW) {
307 PRINT_D(CFG80211_DBG, "Shadow network reached its maximum limit\n");
310 if (ap_found == -1) {
311 ap_index = u32LastScannedNtwrksCountShadow;
312 u32LastScannedNtwrksCountShadow++;
317 rssi_index = astrLastScannedNtwrksShadow[ap_index].strRssi.u8Index;
318 astrLastScannedNtwrksShadow[ap_index].strRssi.as8RSSI[rssi_index++] = pstrNetworkInfo->s8rssi;
319 if (rssi_index == NUM_RSSI) {
321 astrLastScannedNtwrksShadow[ap_index].strRssi.u8Full = 1;
323 astrLastScannedNtwrksShadow[ap_index].strRssi.u8Index = rssi_index;
325 astrLastScannedNtwrksShadow[ap_index].s8rssi = pstrNetworkInfo->s8rssi;
326 astrLastScannedNtwrksShadow[ap_index].u16CapInfo = pstrNetworkInfo->u16CapInfo;
328 astrLastScannedNtwrksShadow[ap_index].u8SsidLen = pstrNetworkInfo->u8SsidLen;
329 memcpy(astrLastScannedNtwrksShadow[ap_index].au8ssid,
330 pstrNetworkInfo->au8ssid, pstrNetworkInfo->u8SsidLen);
332 memcpy(astrLastScannedNtwrksShadow[ap_index].au8bssid,
333 pstrNetworkInfo->au8bssid, ETH_ALEN);
335 astrLastScannedNtwrksShadow[ap_index].u16BeaconPeriod = pstrNetworkInfo->u16BeaconPeriod;
336 astrLastScannedNtwrksShadow[ap_index].u8DtimPeriod = pstrNetworkInfo->u8DtimPeriod;
337 astrLastScannedNtwrksShadow[ap_index].u8channel = pstrNetworkInfo->u8channel;
339 astrLastScannedNtwrksShadow[ap_index].u16IEsLen = pstrNetworkInfo->u16IEsLen;
340 astrLastScannedNtwrksShadow[ap_index].u64Tsf = pstrNetworkInfo->u64Tsf;
342 kfree(astrLastScannedNtwrksShadow[ap_index].pu8IEs);
343 astrLastScannedNtwrksShadow[ap_index].pu8IEs =
344 kmalloc(pstrNetworkInfo->u16IEsLen, GFP_KERNEL); /* will be deallocated by the WILC_WFI_CfgScan() function */
345 memcpy(astrLastScannedNtwrksShadow[ap_index].pu8IEs,
346 pstrNetworkInfo->pu8IEs, pstrNetworkInfo->u16IEsLen);
348 astrLastScannedNtwrksShadow[ap_index].u32TimeRcvdInScan = jiffies;
349 astrLastScannedNtwrksShadow[ap_index].u32TimeRcvdInScanCached = jiffies;
350 astrLastScannedNtwrksShadow[ap_index].u8Found = 1;
352 host_int_freeJoinParams(astrLastScannedNtwrksShadow[ap_index].pJoinParams);
353 astrLastScannedNtwrksShadow[ap_index].pJoinParams = pJoinParams;
359 * @brief CfgScanResult
360 * @details Callback function which returns the scan results found
362 * @param[in] tenuScanEvent enuScanEvent: enum, indicating the scan event triggered, whether that is
363 * SCAN_EVENT_NETWORK_FOUND or SCAN_EVENT_DONE
364 * tstrNetworkInfo* pstrNetworkInfo: structure holding the scan results information
365 * void* pUserVoid: Private structure associated with the wireless interface
371 static void CfgScanResult(tenuScanEvent enuScanEvent, tstrNetworkInfo *pstrNetworkInfo, void *pUserVoid, void *pJoinParams)
373 struct wilc_priv *priv;
376 struct ieee80211_channel *channel;
377 s32 s32Error = WILC_SUCCESS;
378 struct cfg80211_bss *bss = NULL;
380 priv = (struct wilc_priv *)pUserVoid;
381 if (priv->bCfgScanning == true) {
382 if (enuScanEvent == SCAN_EVENT_NETWORK_FOUND) {
383 wiphy = priv->dev->ieee80211_ptr->wiphy;
384 WILC_NULLCHECK(s32Error, wiphy);
385 if (wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC
387 ((((s32)pstrNetworkInfo->s8rssi) * 100) < 0
389 (((s32)pstrNetworkInfo->s8rssi) * 100) > 100)
391 WILC_ERRORREPORT(s32Error, WILC_FAIL);
394 if (pstrNetworkInfo != NULL) {
395 s32Freq = ieee80211_channel_to_frequency((s32)pstrNetworkInfo->u8channel, IEEE80211_BAND_2GHZ);
396 channel = ieee80211_get_channel(wiphy, s32Freq);
398 WILC_NULLCHECK(s32Error, channel);
400 PRINT_INFO(CFG80211_DBG, "Network Info:: CHANNEL Frequency: %d, RSSI: %d, CapabilityInfo: %d,"
401 "BeaconPeriod: %d\n", channel->center_freq, (((s32)pstrNetworkInfo->s8rssi) * 100),
402 pstrNetworkInfo->u16CapInfo, pstrNetworkInfo->u16BeaconPeriod);
404 if (pstrNetworkInfo->bNewNetwork == true) {
405 if (priv->u32RcvdChCount < MAX_NUM_SCANNED_NETWORKS) { /* TODO: mostafa: to be replaced by */
407 PRINT_D(CFG80211_DBG, "Network %s found\n", pstrNetworkInfo->au8ssid);
410 priv->u32RcvdChCount++;
414 if (pJoinParams == NULL) {
415 PRINT_INFO(CORECONFIG_DBG, ">> Something really bad happened\n");
417 add_network_to_shadow(pstrNetworkInfo, priv, pJoinParams);
419 /*P2P peers are sent to WPA supplicant and added to shadow table*/
421 if (!(memcmp("DIRECT-", pstrNetworkInfo->au8ssid, 7))) {
422 bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, pstrNetworkInfo->au8bssid, pstrNetworkInfo->u64Tsf, pstrNetworkInfo->u16CapInfo,
423 pstrNetworkInfo->u16BeaconPeriod, (const u8 *)pstrNetworkInfo->pu8IEs,
424 (size_t)pstrNetworkInfo->u16IEsLen, (((s32)pstrNetworkInfo->s8rssi) * 100), GFP_KERNEL);
425 cfg80211_put_bss(wiphy, bss);
430 PRINT_ER("Discovered networks exceeded the max limit\n");
434 /* So this network is discovered before, we'll just update its RSSI */
435 for (i = 0; i < priv->u32RcvdChCount; i++) {
436 if (memcmp(astrLastScannedNtwrksShadow[i].au8bssid, pstrNetworkInfo->au8bssid, 6) == 0) {
437 PRINT_D(CFG80211_DBG, "Update RSSI of %s\n", astrLastScannedNtwrksShadow[i].au8ssid);
439 astrLastScannedNtwrksShadow[i].s8rssi = pstrNetworkInfo->s8rssi;
440 astrLastScannedNtwrksShadow[i].u32TimeRcvdInScan = jiffies;
446 } else if (enuScanEvent == SCAN_EVENT_DONE) {
447 PRINT_D(CFG80211_DBG, "Scan Done[%p]\n", priv->dev);
448 PRINT_D(CFG80211_DBG, "Refreshing Scan ...\n");
449 refresh_scan(priv, 1, false);
451 if (priv->u32RcvdChCount > 0)
452 PRINT_D(CFG80211_DBG, "%d Network(s) found\n", priv->u32RcvdChCount);
454 PRINT_D(CFG80211_DBG, "No networks found\n");
456 down(&(priv->hSemScanReq));
458 if (priv->pstrScanReq != NULL) {
459 cfg80211_scan_done(priv->pstrScanReq, false);
460 priv->u32RcvdChCount = 0;
461 priv->bCfgScanning = false;
462 priv->pstrScanReq = NULL;
464 up(&(priv->hSemScanReq));
467 /*Aborting any scan operation during mac close*/
468 else if (enuScanEvent == SCAN_EVENT_ABORTED) {
469 down(&(priv->hSemScanReq));
471 PRINT_D(CFG80211_DBG, "Scan Aborted\n");
472 if (priv->pstrScanReq != NULL) {
474 update_scan_time(priv);
475 refresh_scan(priv, 1, false);
477 cfg80211_scan_done(priv->pstrScanReq, false);
478 priv->bCfgScanning = false;
479 priv->pstrScanReq = NULL;
481 up(&(priv->hSemScanReq));
493 * @brief WILC_WFI_Set_PMKSA
494 * @details Check if pmksa is cached and set it.
496 * @return int : Return 0 on Success
501 int WILC_WFI_Set_PMKSA(u8 *bssid, struct wilc_priv *priv)
504 s32 s32Error = WILC_SUCCESS;
507 for (i = 0; i < priv->pmkid_list.numpmkid; i++) {
509 if (!memcmp(bssid, priv->pmkid_list.pmkidlist[i].bssid,
511 PRINT_D(CFG80211_DBG, "PMKID successful comparison");
513 /*If bssid is found, set the values*/
514 s32Error = host_int_set_pmkid_info(priv->hWILCWFIDrv, &priv->pmkid_list);
516 if (s32Error != WILC_SUCCESS)
517 PRINT_ER("Error in pmkid\n");
527 int linux_wlan_set_bssid(struct net_device *wilc_netdev, u8 *pBSSID);
531 * @brief CfgConnectResult
533 * @param[in] tenuConnDisconnEvent enuConnDisconnEvent: Type of connection response either
534 * connection response or disconnection notification.
535 * tstrConnectInfo* pstrConnectInfo: COnnection information.
536 * u8 u8MacStatus: Mac Status from firmware
537 * tstrDisconnectNotifInfo* pstrDisconnectNotifInfo: Disconnection Notification
538 * void* pUserVoid: Private data associated with wireless interface
546 static void CfgConnectResult(tenuConnDisconnEvent enuConnDisconnEvent,
547 tstrConnectInfo *pstrConnectInfo,
549 tstrDisconnectNotifInfo *pstrDisconnectNotifInfo,
552 struct wilc_priv *priv;
553 struct net_device *dev;
555 tstrWILC_WFIDrv *pstrWFIDrv;
557 u8 NullBssid[ETH_ALEN] = {0};
561 priv = (struct wilc_priv *)pUserVoid;
564 pstrWFIDrv = (tstrWILC_WFIDrv *)priv->hWILCWFIDrv;
567 if (enuConnDisconnEvent == CONN_DISCONN_EVENT_CONN_RESP) {
569 u16 u16ConnectStatus = WLAN_STATUS_SUCCESS;
571 u16ConnectStatus = pstrConnectInfo->u16ConnectStatus;
573 PRINT_D(CFG80211_DBG, " Connection response received = %d\n", u8MacStatus);
575 if ((u8MacStatus == MAC_DISCONNECTED) &&
576 (pstrConnectInfo->u16ConnectStatus == SUCCESSFUL_STATUSCODE)) {
577 /* The case here is that our station was waiting for association response frame and has just received it containing status code
578 * = SUCCESSFUL_STATUSCODE, while mac status is MAC_DISCONNECTED (which means something wrong happened) */
579 u16ConnectStatus = WLAN_STATUS_UNSPECIFIED_FAILURE;
580 linux_wlan_set_bssid(priv->dev, NullBssid);
581 memset(u8ConnectedSSID, 0, ETH_ALEN);
584 /*Invalidate u8WLANChannel value on wlan0 disconnect*/
586 if (!pstrWFIDrv->u8P2PConnect)
587 u8WLANChannel = INVALID_CHANNEL;
590 PRINT_ER("Unspecified failure: Connection status %d : MAC status = %d\n", u16ConnectStatus, u8MacStatus);
593 if (u16ConnectStatus == WLAN_STATUS_SUCCESS) {
594 bool bNeedScanRefresh = false;
597 PRINT_INFO(CFG80211_DBG, "Connection Successful:: BSSID: %x%x%x%x%x%x\n", pstrConnectInfo->au8bssid[0],
598 pstrConnectInfo->au8bssid[1], pstrConnectInfo->au8bssid[2], pstrConnectInfo->au8bssid[3], pstrConnectInfo->au8bssid[4], pstrConnectInfo->au8bssid[5]);
599 memcpy(priv->au8AssociatedBss, pstrConnectInfo->au8bssid, ETH_ALEN);
601 /* BugID_4209: if this network has expired in the scan results in the above nl80211 layer, refresh them here by calling
602 * cfg80211_inform_bss() with the last Scan results before calling cfg80211_connect_result() to avoid
603 * Linux kernel warning generated at the nl80211 layer */
605 for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
606 if (memcmp(astrLastScannedNtwrksShadow[i].au8bssid,
607 pstrConnectInfo->au8bssid, ETH_ALEN) == 0) {
608 unsigned long now = jiffies;
611 astrLastScannedNtwrksShadow[i].u32TimeRcvdInScanCached + (unsigned long)(nl80211_SCAN_RESULT_EXPIRE - (1 * HZ)))) {
612 bNeedScanRefresh = true;
619 if (bNeedScanRefresh) {
621 /*Also, refrsh DIRECT- results if */
622 refresh_scan(priv, 1, true);
629 PRINT_D(CFG80211_DBG, "Association request info elements length = %zu\n", pstrConnectInfo->ReqIEsLen);
631 PRINT_D(CFG80211_DBG, "Association response info elements length = %d\n", pstrConnectInfo->u16RespIEsLen);
633 cfg80211_connect_result(dev, pstrConnectInfo->au8bssid,
634 pstrConnectInfo->pu8ReqIEs, pstrConnectInfo->ReqIEsLen,
635 pstrConnectInfo->pu8RespIEs, pstrConnectInfo->u16RespIEsLen,
636 u16ConnectStatus, GFP_KERNEL); /* TODO: mostafa: u16ConnectStatus to */
637 /* be replaced by pstrConnectInfo->u16ConnectStatus */
638 } else if (enuConnDisconnEvent == CONN_DISCONN_EVENT_DISCONN_NOTIF) {
639 #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
640 g_obtainingIP = false;
642 PRINT_ER("Received MAC_DISCONNECTED from firmware with reason %d on dev [%p]\n",
643 pstrDisconnectNotifInfo->u16reason, priv->dev);
644 u8P2Plocalrandom = 0x01;
645 u8P2Precvrandom = 0x00;
647 memset(priv->au8AssociatedBss, 0, ETH_ALEN);
648 linux_wlan_set_bssid(priv->dev, NullBssid);
649 memset(u8ConnectedSSID, 0, ETH_ALEN);
652 /*Invalidate u8WLANChannel value on wlan0 disconnect*/
654 if (!pstrWFIDrv->u8P2PConnect)
655 u8WLANChannel = INVALID_CHANNEL;
658 /*Incase "P2P CLIENT Connected" send deauthentication reason by 3 to force the WPA_SUPPLICANT to directly change
659 * virtual interface to station*/
660 if ((pstrWFIDrv->IFC_UP) && (dev == g_linux_wlan->strInterfaceInfo[1].wilc_netdev)) {
661 pstrDisconnectNotifInfo->u16reason = 3;
664 /*Incase "P2P CLIENT during connection(not connected)" send deauthentication reason by 1 to force the WPA_SUPPLICANT
665 * to scan again and retry the connection*/
666 else if ((!pstrWFIDrv->IFC_UP) && (dev == g_linux_wlan->strInterfaceInfo[1].wilc_netdev)) {
667 pstrDisconnectNotifInfo->u16reason = 1;
669 cfg80211_disconnected(dev, pstrDisconnectNotifInfo->u16reason, pstrDisconnectNotifInfo->ie,
670 pstrDisconnectNotifInfo->ie_len, false,
680 * @details Set channel for a given wireless interface. Some devices
681 * may support multi-channel operation (by channel hopping) so cfg80211
682 * doesn't verify much. Note, however, that the passed netdev may be
683 * %NULL as well if the user requested changing the channel for the
684 * device itself, or for a monitor interface.
686 * @return int : Return 0 on Success
691 static int set_channel(struct wiphy *wiphy,
692 struct cfg80211_chan_def *chandef)
696 struct wilc_priv *priv;
697 s32 s32Error = WILC_SUCCESS;
699 priv = wiphy_priv(wiphy);
701 channelnum = ieee80211_frequency_to_channel(chandef->chan->center_freq);
702 PRINT_D(CFG80211_DBG, "Setting channel %d with frequency %d\n", channelnum, chandef->chan->center_freq);
704 u8CurrChannel = channelnum;
705 s32Error = host_int_set_mac_chnl_num(priv->hWILCWFIDrv, channelnum);
707 if (s32Error != WILC_SUCCESS)
708 PRINT_ER("Error in setting channel %d\n", channelnum);
715 * @details Request to do a scan. If returning zero, the scan request is given
716 * the driver, and will be valid until passed to cfg80211_scan_done().
717 * For scan results, call cfg80211_inform_bss(); you can call this outside
718 * the scan/scan_done bracket too.
720 * @return int : Return 0 on Success
727 * kernel version 3.8.8 supported
728 * tony, sswd, WILC-KR, 2013-10-29
730 static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
732 struct wilc_priv *priv;
734 s32 s32Error = WILC_SUCCESS;
735 u8 au8ScanChanList[MAX_NUM_SCANNED_NETWORKS];
736 tstrHiddenNetwork strHiddenNetwork;
738 priv = wiphy_priv(wiphy);
740 priv->pstrScanReq = request;
742 priv->u32RcvdChCount = 0;
744 host_int_set_wfi_drv_handler(priv->hWILCWFIDrv);
747 reset_shadow_found(priv);
749 priv->bCfgScanning = true;
750 if (request->n_channels <= MAX_NUM_SCANNED_NETWORKS) { /* TODO: mostafa: to be replaced by */
752 for (i = 0; i < request->n_channels; i++) {
753 au8ScanChanList[i] = (u8)ieee80211_frequency_to_channel(request->channels[i]->center_freq);
754 PRINT_INFO(CFG80211_DBG, "ScanChannel List[%d] = %d,", i, au8ScanChanList[i]);
757 PRINT_D(CFG80211_DBG, "Requested num of scan channel %d\n", request->n_channels);
758 PRINT_D(CFG80211_DBG, "Scan Request IE len = %zu\n", request->ie_len);
760 PRINT_D(CFG80211_DBG, "Number of SSIDs %d\n", request->n_ssids);
762 if (request->n_ssids >= 1) {
765 strHiddenNetwork.pstrHiddenNetworkInfo = kmalloc(request->n_ssids * sizeof(tstrHiddenNetwork), GFP_KERNEL);
766 strHiddenNetwork.u8ssidnum = request->n_ssids;
770 for (i = 0; i < request->n_ssids; i++) {
772 if (request->ssids[i].ssid != NULL && request->ssids[i].ssid_len != 0) {
773 strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid = kmalloc(request->ssids[i].ssid_len, GFP_KERNEL);
774 memcpy(strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid, request->ssids[i].ssid, request->ssids[i].ssid_len);
775 strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen = request->ssids[i].ssid_len;
777 PRINT_D(CFG80211_DBG, "Received one NULL SSID\n");
778 strHiddenNetwork.u8ssidnum -= 1;
781 PRINT_D(CFG80211_DBG, "Trigger Scan Request\n");
782 s32Error = host_int_scan(priv->hWILCWFIDrv, USER_SCAN, ACTIVE_SCAN,
783 au8ScanChanList, request->n_channels,
784 (const u8 *)request->ie, request->ie_len,
785 CfgScanResult, (void *)priv, &strHiddenNetwork);
787 PRINT_D(CFG80211_DBG, "Trigger Scan Request\n");
788 s32Error = host_int_scan(priv->hWILCWFIDrv, USER_SCAN, ACTIVE_SCAN,
789 au8ScanChanList, request->n_channels,
790 (const u8 *)request->ie, request->ie_len,
791 CfgScanResult, (void *)priv, NULL);
795 PRINT_ER("Requested num of scanned channels is greater than the max, supported"
799 if (s32Error != WILC_SUCCESS) {
801 PRINT_WRN(CFG80211_DBG, "Device is busy: Error(%d)\n", s32Error);
809 * @details Connect to the ESS with the specified parameters. When connected,
810 * call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS.
811 * If the connection fails for some reason, call cfg80211_connect_result()
812 * with the status from the AP.
814 * @return int : Return 0 on Success
819 static int connect(struct wiphy *wiphy, struct net_device *dev,
820 struct cfg80211_connect_params *sme)
822 s32 s32Error = WILC_SUCCESS;
824 u8 u8security = NO_ENCRYPT;
825 AUTHTYPE_T tenuAuth_type = ANY;
826 char *pcgroup_encrypt_val = NULL;
827 char *pccipher_group = NULL;
828 char *pcwpa_version = NULL;
830 struct wilc_priv *priv;
831 tstrWILC_WFIDrv *pstrWFIDrv;
832 tstrNetworkInfo *pstrNetworkInfo = NULL;
836 priv = wiphy_priv(wiphy);
837 pstrWFIDrv = (tstrWILC_WFIDrv *)(priv->hWILCWFIDrv);
839 host_int_set_wfi_drv_handler(priv->hWILCWFIDrv);
841 PRINT_D(CFG80211_DBG, "Connecting to SSID [%s] on netdev [%p] host if [%p]\n", sme->ssid, dev, priv->hWILCWFIDrv);
843 if (!(strncmp(sme->ssid, "DIRECT-", 7))) {
844 PRINT_D(CFG80211_DBG, "Connected to Direct network,OBSS disabled\n");
845 pstrWFIDrv->u8P2PConnect = 1;
847 pstrWFIDrv->u8P2PConnect = 0;
849 PRINT_INFO(CFG80211_DBG, "Required SSID = %s\n , AuthType = %d\n", sme->ssid, sme->auth_type);
851 for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
852 if ((sme->ssid_len == astrLastScannedNtwrksShadow[i].u8SsidLen) &&
853 memcmp(astrLastScannedNtwrksShadow[i].au8ssid,
855 sme->ssid_len) == 0) {
856 PRINT_INFO(CFG80211_DBG, "Network with required SSID is found %s\n", sme->ssid);
857 if (sme->bssid == NULL) {
858 /* BSSID is not passed from the user, so decision of matching
859 * is done by SSID only */
860 PRINT_INFO(CFG80211_DBG, "BSSID is not passed from the user\n");
863 /* BSSID is also passed from the user, so decision of matching
864 * should consider also this passed BSSID */
865 if (memcmp(astrLastScannedNtwrksShadow[i].au8bssid,
868 PRINT_INFO(CFG80211_DBG, "BSSID is passed from the user and matched\n");
875 if (i < u32LastScannedNtwrksCountShadow) {
876 PRINT_D(CFG80211_DBG, "Required bss is in scan results\n");
878 pstrNetworkInfo = &(astrLastScannedNtwrksShadow[i]);
880 PRINT_INFO(CFG80211_DBG, "network BSSID to be associated: %x%x%x%x%x%x\n",
881 pstrNetworkInfo->au8bssid[0], pstrNetworkInfo->au8bssid[1],
882 pstrNetworkInfo->au8bssid[2], pstrNetworkInfo->au8bssid[3],
883 pstrNetworkInfo->au8bssid[4], pstrNetworkInfo->au8bssid[5]);
886 if (u32LastScannedNtwrksCountShadow == 0)
887 PRINT_D(CFG80211_DBG, "No Scan results yet\n");
889 PRINT_D(CFG80211_DBG, "Required bss not in scan results: Error(%d)\n", s32Error);
894 priv->WILC_WFI_wep_default = 0;
895 memset(priv->WILC_WFI_wep_key, 0, sizeof(priv->WILC_WFI_wep_key));
896 memset(priv->WILC_WFI_wep_key_len, 0, sizeof(priv->WILC_WFI_wep_key_len));
898 PRINT_INFO(CFG80211_DBG, "sme->crypto.wpa_versions=%x\n", sme->crypto.wpa_versions);
899 PRINT_INFO(CFG80211_DBG, "sme->crypto.cipher_group=%x\n", sme->crypto.cipher_group);
901 PRINT_INFO(CFG80211_DBG, "sme->crypto.n_ciphers_pairwise=%d\n", sme->crypto.n_ciphers_pairwise);
904 for (i = 0; i < sme->crypto.n_ciphers_pairwise; i++)
905 PRINT_D(CORECONFIG_DBG, "sme->crypto.ciphers_pairwise[%d]=%x\n", i, sme->crypto.ciphers_pairwise[i]);
908 if (sme->crypto.cipher_group != NO_ENCRYPT) {
909 /* To determine the u8security value, first we check the group cipher suite then {in case of WPA or WPA2}
910 * we will add to it the pairwise cipher suite(s) */
911 pcwpa_version = "Default";
912 PRINT_D(CORECONFIG_DBG, ">> sme->crypto.wpa_versions: %x\n", sme->crypto.wpa_versions);
913 if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) {
914 u8security = ENCRYPT_ENABLED | WEP;
915 pcgroup_encrypt_val = "WEP40";
916 pccipher_group = "WLAN_CIPHER_SUITE_WEP40";
917 PRINT_INFO(CFG80211_DBG, "WEP Default Key Idx = %d\n", sme->key_idx);
920 for (i = 0; i < sme->key_len; i++)
921 PRINT_D(CORECONFIG_DBG, "WEP Key Value[%d] = %d\n", i, sme->key[i]);
923 priv->WILC_WFI_wep_default = sme->key_idx;
924 priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len;
925 memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len);
928 g_key_wep_params.key_len = sme->key_len;
929 g_key_wep_params.key = kmalloc(sme->key_len, GFP_KERNEL);
930 memcpy(g_key_wep_params.key, sme->key, sme->key_len);
931 g_key_wep_params.key_idx = sme->key_idx;
932 g_wep_keys_saved = true;
934 host_int_set_WEPDefaultKeyID(priv->hWILCWFIDrv, sme->key_idx);
935 host_int_add_wep_key_bss_sta(priv->hWILCWFIDrv, sme->key, sme->key_len, sme->key_idx);
936 } else if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104) {
937 u8security = ENCRYPT_ENABLED | WEP | WEP_EXTENDED;
938 pcgroup_encrypt_val = "WEP104";
939 pccipher_group = "WLAN_CIPHER_SUITE_WEP104";
941 priv->WILC_WFI_wep_default = sme->key_idx;
942 priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len;
943 memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len);
946 g_key_wep_params.key_len = sme->key_len;
947 g_key_wep_params.key = kmalloc(sme->key_len, GFP_KERNEL);
948 memcpy(g_key_wep_params.key, sme->key, sme->key_len);
949 g_key_wep_params.key_idx = sme->key_idx;
950 g_wep_keys_saved = true;
952 host_int_set_WEPDefaultKeyID(priv->hWILCWFIDrv, sme->key_idx);
953 host_int_add_wep_key_bss_sta(priv->hWILCWFIDrv, sme->key, sme->key_len, sme->key_idx);
954 } else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) {
955 if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_TKIP) {
956 u8security = ENCRYPT_ENABLED | WPA2 | TKIP;
957 pcgroup_encrypt_val = "WPA2_TKIP";
958 pccipher_group = "TKIP";
959 } else { /* TODO: mostafa: here we assume that any other encryption type is AES */
960 /* tenuSecurity_t = WPA2_AES; */
961 u8security = ENCRYPT_ENABLED | WPA2 | AES;
962 pcgroup_encrypt_val = "WPA2_AES";
963 pccipher_group = "AES";
965 pcwpa_version = "WPA_VERSION_2";
966 } else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) {
967 if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_TKIP) {
968 u8security = ENCRYPT_ENABLED | WPA | TKIP;
969 pcgroup_encrypt_val = "WPA_TKIP";
970 pccipher_group = "TKIP";
971 } else { /* TODO: mostafa: here we assume that any other encryption type is AES */
972 /* tenuSecurity_t = WPA_AES; */
973 u8security = ENCRYPT_ENABLED | WPA | AES;
974 pcgroup_encrypt_val = "WPA_AES";
975 pccipher_group = "AES";
978 pcwpa_version = "WPA_VERSION_1";
981 s32Error = -ENOTSUPP;
982 PRINT_ER("Not supported cipher: Error(%d)\n", s32Error);
989 /* After we set the u8security value from checking the group cipher suite, {in case of WPA or WPA2} we will
990 * add to it the pairwise cipher suite(s) */
991 if ((sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
992 || (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)) {
993 for (i = 0; i < sme->crypto.n_ciphers_pairwise; i++) {
994 if (sme->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP) {
995 u8security = u8security | TKIP;
996 } else { /* TODO: mostafa: here we assume that any other encryption type is AES */
997 u8security = u8security | AES;
1002 PRINT_D(CFG80211_DBG, "Adding key with cipher group = %x\n", sme->crypto.cipher_group);
1004 PRINT_D(CFG80211_DBG, "Authentication Type = %d\n", sme->auth_type);
1005 switch (sme->auth_type) {
1006 case NL80211_AUTHTYPE_OPEN_SYSTEM:
1007 PRINT_D(CFG80211_DBG, "In OPEN SYSTEM\n");
1008 tenuAuth_type = OPEN_SYSTEM;
1011 case NL80211_AUTHTYPE_SHARED_KEY:
1012 tenuAuth_type = SHARED_KEY;
1013 PRINT_D(CFG80211_DBG, "In SHARED KEY\n");
1017 PRINT_D(CFG80211_DBG, "Automatic Authentation type = %d\n", sme->auth_type);
1021 /* ai: key_mgmt: enterprise case */
1022 if (sme->crypto.n_akm_suites) {
1023 switch (sme->crypto.akm_suites[0]) {
1024 case WLAN_AKM_SUITE_8021X:
1025 tenuAuth_type = IEEE8021;
1034 PRINT_INFO(CFG80211_DBG, "Required Channel = %d\n", pstrNetworkInfo->u8channel);
1036 PRINT_INFO(CFG80211_DBG, "Group encryption value = %s\n Cipher Group = %s\n WPA version = %s\n",
1037 pcgroup_encrypt_val, pccipher_group, pcwpa_version);
1040 u8CurrChannel = pstrNetworkInfo->u8channel;
1042 if (!pstrWFIDrv->u8P2PConnect) {
1043 u8WLANChannel = pstrNetworkInfo->u8channel;
1046 linux_wlan_set_bssid(dev, pstrNetworkInfo->au8bssid);
1048 s32Error = host_int_set_join_req(priv->hWILCWFIDrv, pstrNetworkInfo->au8bssid, sme->ssid,
1049 sme->ssid_len, sme->ie, sme->ie_len,
1050 CfgConnectResult, (void *)priv, u8security,
1051 tenuAuth_type, pstrNetworkInfo->u8channel,
1052 pstrNetworkInfo->pJoinParams);
1053 if (s32Error != WILC_SUCCESS) {
1054 PRINT_ER("host_int_set_join_req(): Error(%d)\n", s32Error);
1067 * @details Disconnect from the BSS/ESS.
1069 * @return int : Return 0 on Success
1074 static int disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code)
1076 s32 s32Error = WILC_SUCCESS;
1077 struct wilc_priv *priv;
1079 tstrWILC_WFIDrv *pstrWFIDrv;
1081 u8 NullBssid[ETH_ALEN] = {0};
1084 priv = wiphy_priv(wiphy);
1087 /*Invalidate u8WLANChannel value on wlan0 disconnect*/
1089 pstrWFIDrv = (tstrWILC_WFIDrv *)priv->hWILCWFIDrv;
1090 if (!pstrWFIDrv->u8P2PConnect)
1091 u8WLANChannel = INVALID_CHANNEL;
1093 linux_wlan_set_bssid(priv->dev, NullBssid);
1095 PRINT_D(CFG80211_DBG, "Disconnecting with reason code(%d)\n", reason_code);
1097 u8P2Plocalrandom = 0x01;
1098 u8P2Precvrandom = 0x00;
1101 pstrWFIDrv->u64P2p_MgmtTimeout = 0;
1104 s32Error = host_int_disconnect(priv->hWILCWFIDrv, reason_code);
1105 if (s32Error != WILC_SUCCESS) {
1106 PRINT_ER("Error in disconnecting: Error(%d)\n", s32Error);
1115 * @details Add a key with the given parameters. @mac_addr will be %NULL
1116 * when adding a group key.
1117 * @param[in] key : key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key, 8-byte Rx Mic Key
1118 * @return int : Return 0 on Success
1123 static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
1125 const u8 *mac_addr, struct key_params *params)
1128 s32 s32Error = WILC_SUCCESS, KeyLen = params->key_len;
1130 struct wilc_priv *priv;
1131 const u8 *pu8RxMic = NULL;
1132 const u8 *pu8TxMic = NULL;
1133 u8 u8mode = NO_ENCRYPT;
1134 #ifdef WILC_AP_EXTERNAL_MLME
1135 u8 u8gmode = NO_ENCRYPT;
1136 u8 u8pmode = NO_ENCRYPT;
1137 AUTHTYPE_T tenuAuth_type = ANY;
1140 priv = wiphy_priv(wiphy);
1142 PRINT_D(CFG80211_DBG, "Adding key with cipher suite = %x\n", params->cipher);
1145 PRINT_D(CFG80211_DBG, "%p %p %d\n", wiphy, netdev, key_index);
1147 PRINT_D(CFG80211_DBG, "key %x %x %x\n", params->key[0],
1152 switch (params->cipher) {
1153 case WLAN_CIPHER_SUITE_WEP40:
1154 case WLAN_CIPHER_SUITE_WEP104:
1155 #ifdef WILC_AP_EXTERNAL_MLME
1156 if (priv->wdev->iftype == NL80211_IFTYPE_AP) {
1158 priv->WILC_WFI_wep_default = key_index;
1159 priv->WILC_WFI_wep_key_len[key_index] = params->key_len;
1160 memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len);
1162 PRINT_D(CFG80211_DBG, "Adding AP WEP Default key Idx = %d\n", key_index);
1163 PRINT_D(CFG80211_DBG, "Adding AP WEP Key len= %d\n", params->key_len);
1165 for (i = 0; i < params->key_len; i++)
1166 PRINT_D(CFG80211_DBG, "WEP AP key val[%d] = %x\n", i, params->key[i]);
1168 tenuAuth_type = OPEN_SYSTEM;
1170 if (params->cipher == WLAN_CIPHER_SUITE_WEP40)
1171 u8mode = ENCRYPT_ENABLED | WEP;
1173 u8mode = ENCRYPT_ENABLED | WEP | WEP_EXTENDED;
1175 host_int_add_wep_key_bss_ap(priv->hWILCWFIDrv, params->key, params->key_len, key_index, u8mode, tenuAuth_type);
1179 if (memcmp(params->key, priv->WILC_WFI_wep_key[key_index], params->key_len)) {
1180 priv->WILC_WFI_wep_default = key_index;
1181 priv->WILC_WFI_wep_key_len[key_index] = params->key_len;
1182 memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len);
1184 PRINT_D(CFG80211_DBG, "Adding WEP Default key Idx = %d\n", key_index);
1185 PRINT_D(CFG80211_DBG, "Adding WEP Key length = %d\n", params->key_len);
1187 for (i = 0; i < params->key_len; i++)
1188 PRINT_INFO(CFG80211_DBG, "WEP key value[%d] = %d\n", i, params->key[i]);
1190 host_int_add_wep_key_bss_sta(priv->hWILCWFIDrv, params->key, params->key_len, key_index);
1195 case WLAN_CIPHER_SUITE_TKIP:
1196 case WLAN_CIPHER_SUITE_CCMP:
1197 #ifdef WILC_AP_EXTERNAL_MLME
1198 if (priv->wdev->iftype == NL80211_IFTYPE_AP || priv->wdev->iftype == NL80211_IFTYPE_P2P_GO) {
1200 if (priv->wilc_gtk[key_index] == NULL) {
1201 priv->wilc_gtk[key_index] = kmalloc(sizeof(struct wilc_wfi_key), GFP_KERNEL);
1202 priv->wilc_gtk[key_index]->key = NULL;
1203 priv->wilc_gtk[key_index]->seq = NULL;
1206 if (priv->wilc_ptk[key_index] == NULL) {
1207 priv->wilc_ptk[key_index] = kmalloc(sizeof(struct wilc_wfi_key), GFP_KERNEL);
1208 priv->wilc_ptk[key_index]->key = NULL;
1209 priv->wilc_ptk[key_index]->seq = NULL;
1215 if (params->cipher == WLAN_CIPHER_SUITE_TKIP)
1216 u8gmode = ENCRYPT_ENABLED | WPA | TKIP;
1218 u8gmode = ENCRYPT_ENABLED | WPA2 | AES;
1220 priv->wilc_groupkey = u8gmode;
1222 if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
1224 pu8TxMic = params->key + 24;
1225 pu8RxMic = params->key + 16;
1226 KeyLen = params->key_len - 16;
1228 /* if there has been previous allocation for the same index through its key, free that memory and allocate again*/
1229 if (priv->wilc_gtk[key_index]->key)
1230 kfree(priv->wilc_gtk[key_index]->key);
1232 priv->wilc_gtk[key_index]->key = kmalloc(params->key_len, GFP_KERNEL);
1233 memcpy(priv->wilc_gtk[key_index]->key, params->key, params->key_len);
1235 /* if there has been previous allocation for the same index through its seq, free that memory and allocate again*/
1236 if (priv->wilc_gtk[key_index]->seq)
1237 kfree(priv->wilc_gtk[key_index]->seq);
1239 if ((params->seq_len) > 0) {
1240 priv->wilc_gtk[key_index]->seq = kmalloc(params->seq_len, GFP_KERNEL);
1241 memcpy(priv->wilc_gtk[key_index]->seq, params->seq, params->seq_len);
1244 priv->wilc_gtk[key_index]->cipher = params->cipher;
1245 priv->wilc_gtk[key_index]->key_len = params->key_len;
1246 priv->wilc_gtk[key_index]->seq_len = params->seq_len;
1249 for (i = 0; i < params->key_len; i++)
1250 PRINT_INFO(CFG80211_DBG, "Adding group key value[%d] = %x\n", i, params->key[i]);
1251 for (i = 0; i < params->seq_len; i++)
1252 PRINT_INFO(CFG80211_DBG, "Adding group seq value[%d] = %x\n", i, params->seq[i]);
1256 host_int_add_rx_gtk(priv->hWILCWFIDrv, params->key, KeyLen,
1257 key_index, params->seq_len, params->seq, pu8RxMic, pu8TxMic, AP_MODE, u8gmode);
1260 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]);
1262 if (params->cipher == WLAN_CIPHER_SUITE_TKIP)
1263 u8pmode = ENCRYPT_ENABLED | WPA | TKIP;
1265 u8pmode = priv->wilc_groupkey | AES;
1268 if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
1270 pu8TxMic = params->key + 24;
1271 pu8RxMic = params->key + 16;
1272 KeyLen = params->key_len - 16;
1275 if (priv->wilc_ptk[key_index]->key)
1276 kfree(priv->wilc_ptk[key_index]->key);
1278 priv->wilc_ptk[key_index]->key = kmalloc(params->key_len, GFP_KERNEL);
1280 if (priv->wilc_ptk[key_index]->seq)
1281 kfree(priv->wilc_ptk[key_index]->seq);
1283 if ((params->seq_len) > 0)
1284 priv->wilc_ptk[key_index]->seq = kmalloc(params->seq_len, GFP_KERNEL);
1287 for (i = 0; i < params->key_len; i++)
1288 PRINT_INFO(CFG80211_DBG, "Adding pairwise key value[%d] = %x\n", i, params->key[i]);
1290 for (i = 0; i < params->seq_len; i++)
1291 PRINT_INFO(CFG80211_DBG, "Adding group seq value[%d] = %x\n", i, params->seq[i]);
1294 memcpy(priv->wilc_ptk[key_index]->key, params->key, params->key_len);
1296 if ((params->seq_len) > 0)
1297 memcpy(priv->wilc_ptk[key_index]->seq, params->seq, params->seq_len);
1299 priv->wilc_ptk[key_index]->cipher = params->cipher;
1300 priv->wilc_ptk[key_index]->key_len = params->key_len;
1301 priv->wilc_ptk[key_index]->seq_len = params->seq_len;
1303 host_int_add_ptk(priv->hWILCWFIDrv, params->key, KeyLen, mac_addr,
1304 pu8RxMic, pu8TxMic, AP_MODE, u8pmode, key_index);
1313 if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
1314 /* swap the tx mic by rx mic */
1315 pu8RxMic = params->key + 24;
1316 pu8TxMic = params->key + 16;
1317 KeyLen = params->key_len - 16;
1321 /*save keys only on interface 0 (wifi interface)*/
1322 if (!g_gtk_keys_saved && netdev == g_linux_wlan->strInterfaceInfo[0].wilc_netdev) {
1323 g_add_gtk_key_params.key_idx = key_index;
1324 g_add_gtk_key_params.pairwise = pairwise;
1326 g_add_gtk_key_params.mac_addr = NULL;
1328 g_add_gtk_key_params.mac_addr = kmalloc(ETH_ALEN, GFP_KERNEL);
1329 memcpy(g_add_gtk_key_params.mac_addr, mac_addr, ETH_ALEN);
1331 g_key_gtk_params.key_len = params->key_len;
1332 g_key_gtk_params.seq_len = params->seq_len;
1333 g_key_gtk_params.key = kmalloc(params->key_len, GFP_KERNEL);
1334 memcpy(g_key_gtk_params.key, params->key, params->key_len);
1335 if (params->seq_len > 0) {
1336 g_key_gtk_params.seq = kmalloc(params->seq_len, GFP_KERNEL);
1337 memcpy(g_key_gtk_params.seq, params->seq, params->seq_len);
1339 g_key_gtk_params.cipher = params->cipher;
1341 PRINT_D(CFG80211_DBG, "key %x %x %x\n", g_key_gtk_params.key[0],
1342 g_key_gtk_params.key[1],
1343 g_key_gtk_params.key[2]);
1344 g_gtk_keys_saved = true;
1347 host_int_add_rx_gtk(priv->hWILCWFIDrv, params->key, KeyLen,
1348 key_index, params->seq_len, params->seq, pu8RxMic, pu8TxMic, STATION_MODE, u8mode);
1350 if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
1351 /* swap the tx mic by rx mic */
1352 pu8RxMic = params->key + 24;
1353 pu8TxMic = params->key + 16;
1354 KeyLen = params->key_len - 16;
1358 /*save keys only on interface 0 (wifi interface)*/
1359 if (!g_ptk_keys_saved && netdev == g_linux_wlan->strInterfaceInfo[0].wilc_netdev) {
1360 g_add_ptk_key_params.key_idx = key_index;
1361 g_add_ptk_key_params.pairwise = pairwise;
1363 g_add_ptk_key_params.mac_addr = NULL;
1365 g_add_ptk_key_params.mac_addr = kmalloc(ETH_ALEN, GFP_KERNEL);
1366 memcpy(g_add_ptk_key_params.mac_addr, mac_addr, ETH_ALEN);
1368 g_key_ptk_params.key_len = params->key_len;
1369 g_key_ptk_params.seq_len = params->seq_len;
1370 g_key_ptk_params.key = kmalloc(params->key_len, GFP_KERNEL);
1371 memcpy(g_key_ptk_params.key, params->key, params->key_len);
1372 if (params->seq_len > 0) {
1373 g_key_ptk_params.seq = kmalloc(params->seq_len, GFP_KERNEL);
1374 memcpy(g_key_ptk_params.seq, params->seq, params->seq_len);
1376 g_key_ptk_params.cipher = params->cipher;
1378 PRINT_D(CFG80211_DBG, "key %x %x %x\n", g_key_ptk_params.key[0],
1379 g_key_ptk_params.key[1],
1380 g_key_ptk_params.key[2]);
1381 g_ptk_keys_saved = true;
1384 host_int_add_ptk(priv->hWILCWFIDrv, params->key, KeyLen, mac_addr,
1385 pu8RxMic, pu8TxMic, STATION_MODE, u8mode, key_index);
1386 PRINT_D(CFG80211_DBG, "Adding pairwise key\n");
1388 for (i = 0; i < params->key_len; i++)
1389 PRINT_INFO(CFG80211_DBG, "Adding pairwise key value[%d] = %d\n", i, params->key[i]);
1396 PRINT_ER("Not supported cipher: Error(%d)\n", s32Error);
1397 s32Error = -ENOTSUPP;
1406 * @details Remove a key given the @mac_addr (%NULL for a group key)
1407 * and @key_index, return -ENOENT if the key doesn't exist.
1409 * @return int : Return 0 on Success
1414 static int del_key(struct wiphy *wiphy, struct net_device *netdev,
1419 struct wilc_priv *priv;
1420 s32 s32Error = WILC_SUCCESS;
1422 priv = wiphy_priv(wiphy);
1425 /*delete saved keys, if any*/
1426 if (netdev == g_linux_wlan->strInterfaceInfo[0].wilc_netdev) {
1427 g_ptk_keys_saved = false;
1428 g_gtk_keys_saved = false;
1429 g_wep_keys_saved = false;
1431 /*Delete saved WEP keys params, if any*/
1432 if (g_key_wep_params.key != NULL) {
1433 kfree(g_key_wep_params.key);
1434 g_key_wep_params.key = NULL;
1437 /*freeing memory allocated by "wilc_gtk" and "wilc_ptk" in "WILC_WIFI_ADD_KEY"*/
1439 #ifdef WILC_AP_EXTERNAL_MLME
1440 if ((priv->wilc_gtk[key_index]) != NULL) {
1442 if (priv->wilc_gtk[key_index]->key != NULL) {
1444 kfree(priv->wilc_gtk[key_index]->key);
1445 priv->wilc_gtk[key_index]->key = NULL;
1447 if (priv->wilc_gtk[key_index]->seq) {
1449 kfree(priv->wilc_gtk[key_index]->seq);
1450 priv->wilc_gtk[key_index]->seq = NULL;
1453 kfree(priv->wilc_gtk[key_index]);
1454 priv->wilc_gtk[key_index] = NULL;
1458 if ((priv->wilc_ptk[key_index]) != NULL) {
1460 if (priv->wilc_ptk[key_index]->key) {
1462 kfree(priv->wilc_ptk[key_index]->key);
1463 priv->wilc_ptk[key_index]->key = NULL;
1465 if (priv->wilc_ptk[key_index]->seq) {
1467 kfree(priv->wilc_ptk[key_index]->seq);
1468 priv->wilc_ptk[key_index]->seq = NULL;
1470 kfree(priv->wilc_ptk[key_index]);
1471 priv->wilc_ptk[key_index] = NULL;
1475 /*Delete saved PTK and GTK keys params, if any*/
1476 if (g_key_ptk_params.key != NULL) {
1477 kfree(g_key_ptk_params.key);
1478 g_key_ptk_params.key = NULL;
1480 if (g_key_ptk_params.seq != NULL) {
1481 kfree(g_key_ptk_params.seq);
1482 g_key_ptk_params.seq = NULL;
1485 if (g_key_gtk_params.key != NULL) {
1486 kfree(g_key_gtk_params.key);
1487 g_key_gtk_params.key = NULL;
1489 if (g_key_gtk_params.seq != NULL) {
1490 kfree(g_key_gtk_params.seq);
1491 g_key_gtk_params.seq = NULL;
1494 /*Reset WILC_CHANGING_VIR_IF register to allow adding futrue keys to CE H/W*/
1495 Set_machw_change_vir_if(false);
1498 if (key_index >= 0 && key_index <= 3) {
1499 memset(priv->WILC_WFI_wep_key[key_index], 0, priv->WILC_WFI_wep_key_len[key_index]);
1500 priv->WILC_WFI_wep_key_len[key_index] = 0;
1502 PRINT_D(CFG80211_DBG, "Removing WEP key with index = %d\n", key_index);
1503 host_int_remove_wep_key(priv->hWILCWFIDrv, key_index);
1505 PRINT_D(CFG80211_DBG, "Removing all installed keys\n");
1506 host_int_remove_key(priv->hWILCWFIDrv, mac_addr);
1514 * @details Get information about the key with the given parameters.
1515 * @mac_addr will be %NULL when requesting information for a group
1516 * key. All pointers given to the @callback function need not be valid
1517 * after it returns. This function should return an error if it is
1518 * not possible to retrieve the key, -ENOENT if it doesn't exist.
1520 * @return int : Return 0 on Success
1525 static int get_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
1527 const u8 *mac_addr, void *cookie, void (*callback)(void *cookie, struct key_params *))
1530 s32 s32Error = WILC_SUCCESS;
1532 struct wilc_priv *priv;
1533 struct key_params key_params;
1536 priv = wiphy_priv(wiphy);
1541 PRINT_D(CFG80211_DBG, "Getting group key idx: %x\n", key_index);
1543 key_params.key = priv->wilc_gtk[key_index]->key;
1544 key_params.cipher = priv->wilc_gtk[key_index]->cipher;
1545 key_params.key_len = priv->wilc_gtk[key_index]->key_len;
1546 key_params.seq = priv->wilc_gtk[key_index]->seq;
1547 key_params.seq_len = priv->wilc_gtk[key_index]->seq_len;
1549 for (i = 0; i < key_params.key_len; i++)
1550 PRINT_INFO(CFG80211_DBG, "Retrieved key value %x\n", key_params.key[i]);
1553 PRINT_D(CFG80211_DBG, "Getting pairwise key\n");
1555 key_params.key = priv->wilc_ptk[key_index]->key;
1556 key_params.cipher = priv->wilc_ptk[key_index]->cipher;
1557 key_params.key_len = priv->wilc_ptk[key_index]->key_len;
1558 key_params.seq = priv->wilc_ptk[key_index]->seq;
1559 key_params.seq_len = priv->wilc_ptk[key_index]->seq_len;
1562 callback(cookie, &key_params);
1564 return s32Error; /* priv->wilc_gtk->key_len ?0 : -ENOENT; */
1568 * @brief set_default_key
1569 * @details Set the default management frame key on an interface
1571 * @return int : Return 0 on Success.
1576 static int set_default_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
1577 bool unicast, bool multicast)
1579 s32 s32Error = WILC_SUCCESS;
1580 struct wilc_priv *priv;
1583 priv = wiphy_priv(wiphy);
1585 PRINT_D(CFG80211_DBG, "Setting default key with idx = %d\n", key_index);
1587 if (key_index != priv->WILC_WFI_wep_default) {
1589 host_int_set_WEPDefaultKeyID(priv->hWILCWFIDrv, key_index);
1596 * @brief WILC_WFI_dump_survey
1597 * @details Get site survey information
1599 * @return int : Return 0 on Success.
1604 static int WILC_WFI_dump_survey(struct wiphy *wiphy, struct net_device *netdev,
1605 int idx, struct survey_info *info)
1607 s32 s32Error = WILC_SUCCESS;
1612 PRINT_ER("Error Idx value doesn't equal zero: Error(%d)\n", s32Error);
1621 * @brief get_station
1622 * @details Get station information for the station identified by @mac
1624 * @return int : Return 0 on Success.
1630 static int get_station(struct wiphy *wiphy, struct net_device *dev,
1631 const u8 *mac, struct station_info *sinfo)
1633 s32 s32Error = WILC_SUCCESS;
1634 struct wilc_priv *priv;
1635 perInterface_wlan_t *nic;
1636 #ifdef WILC_AP_EXTERNAL_MLME
1638 u32 associatedsta = 0;
1639 u32 inactive_time = 0;
1641 priv = wiphy_priv(wiphy);
1642 nic = netdev_priv(dev);
1644 #ifdef WILC_AP_EXTERNAL_MLME
1645 if (nic->iftype == AP_MODE || nic->iftype == GO_MODE) {
1646 PRINT_D(HOSTAPD_DBG, "Getting station parameters\n");
1648 PRINT_INFO(HOSTAPD_DBG, ": %x%x%x%x%x\n", mac[0], mac[1], mac[2], mac[3], mac[4]);
1650 for (i = 0; i < NUM_STA_ASSOCIATED; i++) {
1652 if (!(memcmp(mac, priv->assoc_stainfo.au8Sta_AssociatedBss[i], ETH_ALEN))) {
1659 if (associatedsta == -1) {
1661 PRINT_ER("Station required is not associated : Error(%d)\n", s32Error);
1666 sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME);
1668 host_int_get_inactive_time(priv->hWILCWFIDrv, mac, &(inactive_time));
1669 sinfo->inactive_time = 1000 * inactive_time;
1670 PRINT_D(CFG80211_DBG, "Inactive time %d\n", sinfo->inactive_time);
1675 if (nic->iftype == STATION_MODE) {
1676 tstrStatistics strStatistics;
1678 host_int_get_statistics(priv->hWILCWFIDrv, &strStatistics);
1682 * tx_failed introduced more than
1683 * kernel version 3.0.0
1685 sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL) |
1686 BIT(NL80211_STA_INFO_RX_PACKETS) |
1687 BIT(NL80211_STA_INFO_TX_PACKETS) |
1688 BIT(NL80211_STA_INFO_TX_FAILED) |
1689 BIT(NL80211_STA_INFO_TX_BITRATE);
1691 sinfo->signal = strStatistics.s8RSSI;
1692 sinfo->rx_packets = strStatistics.u32RxCount;
1693 sinfo->tx_packets = strStatistics.u32TxCount + strStatistics.u32TxFailureCount;
1694 sinfo->tx_failed = strStatistics.u32TxFailureCount;
1695 sinfo->txrate.legacy = strStatistics.u8LinkSpeed * 10;
1697 #ifdef TCP_ENHANCEMENTS
1698 if ((strStatistics.u8LinkSpeed > TCP_ACK_FILTER_LINK_SPEED_THRESH) && (strStatistics.u8LinkSpeed != DEFAULT_LINK_SPEED))
1699 Enable_TCP_ACK_Filter(true);
1700 else if (strStatistics.u8LinkSpeed != DEFAULT_LINK_SPEED)
1701 Enable_TCP_ACK_Filter(false);
1704 PRINT_D(CORECONFIG_DBG, "*** stats[%d][%d][%d][%d][%d]\n", sinfo->signal, sinfo->rx_packets, sinfo->tx_packets,
1705 sinfo->tx_failed, sinfo->txrate.legacy);
1713 * @details Modify parameters for a given BSS.
1715 * -use_cts_prot: Whether to use CTS protection
1716 * (0 = no, 1 = yes, -1 = do not change)
1717 * -use_short_preamble: Whether the use of short preambles is allowed
1718 * (0 = no, 1 = yes, -1 = do not change)
1719 * -use_short_slot_time: Whether the use of short slot time is allowed
1720 * (0 = no, 1 = yes, -1 = do not change)
1721 * -basic_rates: basic rates in IEEE 802.11 format
1722 * (or NULL for no change)
1723 * -basic_rates_len: number of basic rates
1724 * -ap_isolate: do not forward packets between connected stations
1725 * -ht_opmode: HT Operation mode
1726 * (u16 = opmode, -1 = do not change)
1727 * @return int : Return 0 on Success.
1732 static int change_bss(struct wiphy *wiphy, struct net_device *dev,
1733 struct bss_parameters *params)
1735 PRINT_D(CFG80211_DBG, "Changing Bss parametrs\n");
1740 * @brief WILC_WFI_auth
1741 * @details Request to authenticate with the specified peer
1743 * @return int : Return 0 on Success.
1748 static int WILC_WFI_auth(struct wiphy *wiphy, struct net_device *dev,
1749 struct cfg80211_auth_request *req)
1751 PRINT_D(CFG80211_DBG, "In Authentication Function\n");
1756 * @brief WILC_WFI_assoc
1757 * @details Request to (re)associate with the specified peer
1759 * @return int : Return 0 on Success.
1764 static int WILC_WFI_assoc(struct wiphy *wiphy, struct net_device *dev,
1765 struct cfg80211_assoc_request *req)
1767 PRINT_D(CFG80211_DBG, "In Association Function\n");
1772 * @brief WILC_WFI_deauth
1773 * @details Request to deauthenticate from the specified peer
1775 * @return int : Return 0 on Success.
1780 static int WILC_WFI_deauth(struct wiphy *wiphy, struct net_device *dev,
1781 struct cfg80211_deauth_request *req, void *cookie)
1783 PRINT_D(CFG80211_DBG, "In De-authentication Function\n");
1788 * @brief WILC_WFI_disassoc
1789 * @details Request to disassociate from the specified peer
1791 * @return int : Return 0 on Success
1796 static int WILC_WFI_disassoc(struct wiphy *wiphy, struct net_device *dev,
1797 struct cfg80211_disassoc_request *req, void *cookie)
1799 PRINT_D(CFG80211_DBG, "In Disassociation Function\n");
1804 * @brief set_wiphy_params
1805 * @details Notify that wiphy parameters have changed;
1806 * @param[in] Changed bitfield (see &enum wiphy_params_flags) describes which values
1808 * @return int : Return 0 on Success
1813 static int set_wiphy_params(struct wiphy *wiphy, u32 changed)
1815 s32 s32Error = WILC_SUCCESS;
1816 tstrCfgParamVal pstrCfgParamVal;
1817 struct wilc_priv *priv;
1819 priv = wiphy_priv(wiphy);
1821 pstrCfgParamVal.u32SetCfgFlag = 0;
1822 PRINT_D(CFG80211_DBG, "Setting Wiphy params\n");
1824 if (changed & WIPHY_PARAM_RETRY_SHORT) {
1825 PRINT_D(CFG80211_DBG, "Setting WIPHY_PARAM_RETRY_SHORT %d\n",
1826 priv->dev->ieee80211_ptr->wiphy->retry_short);
1827 pstrCfgParamVal.u32SetCfgFlag |= RETRY_SHORT;
1828 pstrCfgParamVal.short_retry_limit = priv->dev->ieee80211_ptr->wiphy->retry_short;
1830 if (changed & WIPHY_PARAM_RETRY_LONG) {
1832 PRINT_D(CFG80211_DBG, "Setting WIPHY_PARAM_RETRY_LONG %d\n", priv->dev->ieee80211_ptr->wiphy->retry_long);
1833 pstrCfgParamVal.u32SetCfgFlag |= RETRY_LONG;
1834 pstrCfgParamVal.long_retry_limit = priv->dev->ieee80211_ptr->wiphy->retry_long;
1837 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
1838 PRINT_D(CFG80211_DBG, "Setting WIPHY_PARAM_FRAG_THRESHOLD %d\n", priv->dev->ieee80211_ptr->wiphy->frag_threshold);
1839 pstrCfgParamVal.u32SetCfgFlag |= FRAG_THRESHOLD;
1840 pstrCfgParamVal.frag_threshold = priv->dev->ieee80211_ptr->wiphy->frag_threshold;
1844 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
1845 PRINT_D(CFG80211_DBG, "Setting WIPHY_PARAM_RTS_THRESHOLD %d\n", priv->dev->ieee80211_ptr->wiphy->rts_threshold);
1847 pstrCfgParamVal.u32SetCfgFlag |= RTS_THRESHOLD;
1848 pstrCfgParamVal.rts_threshold = priv->dev->ieee80211_ptr->wiphy->rts_threshold;
1852 PRINT_D(CFG80211_DBG, "Setting CFG params in the host interface\n");
1853 s32Error = hif_set_cfg(priv->hWILCWFIDrv, &pstrCfgParamVal);
1855 PRINT_ER("Error in setting WIPHY PARAMS\n");
1862 * @brief WILC_WFI_set_bitrate_mask
1863 * @details set the bitrate mask configuration
1865 * @return int : Return 0 on Success
1870 static int WILC_WFI_set_bitrate_mask(struct wiphy *wiphy,
1871 struct net_device *dev, const u8 *peer,
1872 const struct cfg80211_bitrate_mask *mask)
1874 s32 s32Error = WILC_SUCCESS;
1876 PRINT_D(CFG80211_DBG, "Setting Bitrate mask function\n");
1883 * @details Cache a PMKID for a BSSID. This is mostly useful for fullmac
1884 * devices running firmwares capable of generating the (re) association
1885 * RSN IE. It allows for faster roaming between WPA2 BSSIDs.
1887 * @return int : Return 0 on Success
1892 static int set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1893 struct cfg80211_pmksa *pmksa)
1896 s32 s32Error = WILC_SUCCESS;
1899 struct wilc_priv *priv = wiphy_priv(wiphy);
1901 PRINT_D(CFG80211_DBG, "Setting PMKSA\n");
1904 for (i = 0; i < priv->pmkid_list.numpmkid; i++) {
1905 if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,
1907 /*If bssid already exists and pmkid value needs to reset*/
1909 PRINT_D(CFG80211_DBG, "PMKID already exists\n");
1913 if (i < WILC_MAX_NUM_PMKIDS) {
1914 PRINT_D(CFG80211_DBG, "Setting PMKID in private structure\n");
1915 memcpy(priv->pmkid_list.pmkidlist[i].bssid, pmksa->bssid,
1917 memcpy(priv->pmkid_list.pmkidlist[i].pmkid, pmksa->pmkid,
1919 if (!(flag == PMKID_FOUND))
1920 priv->pmkid_list.numpmkid++;
1922 PRINT_ER("Invalid PMKID index\n");
1927 PRINT_D(CFG80211_DBG, "Setting pmkid in the host interface\n");
1928 s32Error = host_int_set_pmkid_info(priv->hWILCWFIDrv, &priv->pmkid_list);
1935 * @details Delete a cached PMKID.
1937 * @return int : Return 0 on Success
1942 static int del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1943 struct cfg80211_pmksa *pmksa)
1948 s32 s32Error = WILC_SUCCESS;
1950 struct wilc_priv *priv = wiphy_priv(wiphy);
1952 PRINT_D(CFG80211_DBG, "Deleting PMKSA keys\n");
1954 for (i = 0; i < priv->pmkid_list.numpmkid; i++) {
1955 if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,
1957 /*If bssid is found, reset the values*/
1958 PRINT_D(CFG80211_DBG, "Reseting PMKID values\n");
1959 memset(&priv->pmkid_list.pmkidlist[i], 0, sizeof(tstrHostIFpmkid));
1965 if (i < priv->pmkid_list.numpmkid && priv->pmkid_list.numpmkid > 0) {
1966 for (; i < (priv->pmkid_list.numpmkid - 1); i++) {
1967 memcpy(priv->pmkid_list.pmkidlist[i].bssid,
1968 priv->pmkid_list.pmkidlist[i + 1].bssid,
1970 memcpy(priv->pmkid_list.pmkidlist[i].pmkid,
1971 priv->pmkid_list.pmkidlist[i].pmkid,
1974 priv->pmkid_list.numpmkid--;
1983 * @brief flush_pmksa
1984 * @details Flush all cached PMKIDs.
1986 * @return int : Return 0 on Success
1991 static int flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
1993 struct wilc_priv *priv = wiphy_priv(wiphy);
1995 PRINT_D(CFG80211_DBG, "Flushing PMKID key values\n");
1997 /*Get cashed Pmkids and set all with zeros*/
1998 memset(&priv->pmkid_list, 0, sizeof(tstrHostIFpmkidAttr));
2006 * @brief WILC_WFI_CfgParseRxAction
2007 * @details Function parses the received frames and modifies the following attributes:
2010 * -Operating Channel
2012 * @param[in] u8* Buffer, u32 length
2019 void WILC_WFI_CfgParseRxAction(u8 *buf, u32 len)
2025 u8 op_channel_attr_index = 0;
2026 u8 channel_list_attr_index = 0;
2028 while (index < len) {
2029 if (buf[index] == GO_INTENT_ATTR_ID) {
2030 buf[index + 3] = (buf[index + 3] & 0x01) | (0x00 << 1);
2033 if (buf[index] == CHANLIST_ATTR_ID)
2034 channel_list_attr_index = index;
2035 else if (buf[index] == OPERCHAN_ATTR_ID)
2036 op_channel_attr_index = index;
2037 index += buf[index + 1] + 3; /* ID,Length byte */
2040 if (u8WLANChannel != INVALID_CHANNEL)
2042 /*Modify channel list attribute*/
2043 if (channel_list_attr_index) {
2044 PRINT_D(GENERIC_DBG, "Modify channel list attribute\n");
2045 for (i = channel_list_attr_index + 3; i < ((channel_list_attr_index + 3) + buf[channel_list_attr_index + 1]); i++) {
2046 if (buf[i] == 0x51) {
2047 for (j = i + 2; j < ((i + 2) + buf[i + 1]); j++) {
2048 buf[j] = u8WLANChannel;
2054 /*Modify operating channel attribute*/
2055 if (op_channel_attr_index) {
2056 PRINT_D(GENERIC_DBG, "Modify operating channel attribute\n");
2057 buf[op_channel_attr_index + 6] = 0x51;
2058 buf[op_channel_attr_index + 7] = u8WLANChannel;
2064 * @brief WILC_WFI_CfgParseTxAction
2065 * @details Function parses the transmitted action frames and modifies the
2066 * GO Intent attribute
2067 * @param[in] u8* Buffer, u32 length, bool bOperChan, u8 iftype
2073 void WILC_WFI_CfgParseTxAction(u8 *buf, u32 len, bool bOperChan, u8 iftype)
2078 u8 op_channel_attr_index = 0;
2079 u8 channel_list_attr_index = 0;
2081 while (index < len) {
2082 if (buf[index] == GO_INTENT_ATTR_ID) {
2083 buf[index + 3] = (buf[index + 3] & 0x01) | (0x0f << 1);
2088 if (buf[index] == CHANLIST_ATTR_ID)
2089 channel_list_attr_index = index;
2090 else if (buf[index] == OPERCHAN_ATTR_ID)
2091 op_channel_attr_index = index;
2092 index += buf[index + 1] + 3; /* ID,Length byte */
2095 if (u8WLANChannel != INVALID_CHANNEL && bOperChan)
2097 /*Modify channel list attribute*/
2098 if (channel_list_attr_index) {
2099 PRINT_D(GENERIC_DBG, "Modify channel list attribute\n");
2100 for (i = channel_list_attr_index + 3; i < ((channel_list_attr_index + 3) + buf[channel_list_attr_index + 1]); i++) {
2101 if (buf[i] == 0x51) {
2102 for (j = i + 2; j < ((i + 2) + buf[i + 1]); j++) {
2103 buf[j] = u8WLANChannel;
2109 /*Modify operating channel attribute*/
2110 if (op_channel_attr_index) {
2111 PRINT_D(GENERIC_DBG, "Modify operating channel attribute\n");
2112 buf[op_channel_attr_index + 6] = 0x51;
2113 buf[op_channel_attr_index + 7] = u8WLANChannel;
2118 /* @brief WILC_WFI_p2p_rx
2123 * @author Mai Daftedar
2128 void WILC_WFI_p2p_rx (struct net_device *dev, u8 *buff, u32 size)
2131 struct wilc_priv *priv;
2132 u32 header, pkt_offset;
2133 tstrWILC_WFIDrv *pstrWFIDrv;
2137 priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
2138 pstrWFIDrv = (tstrWILC_WFIDrv *)priv->hWILCWFIDrv;
2140 /* Get WILC header */
2141 memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET);
2143 /* The packet offset field conain info about what type of managment frame */
2144 /* we are dealing with and ack status */
2145 pkt_offset = GET_PKT_OFFSET(header);
2147 if (pkt_offset & IS_MANAGMEMENT_CALLBACK) {
2148 if (buff[FRAME_TYPE_ID] == IEEE80211_STYPE_PROBE_RESP) {
2149 PRINT_D(GENERIC_DBG, "Probe response ACK\n");
2150 cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL);
2153 if (pkt_offset & IS_MGMT_STATUS_SUCCES) {
2154 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],
2155 buff[ACTION_SUBTYPE_ID + 1], buff[P2P_PUB_ACTION_SUBTYPE + 1]);
2156 cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL);
2158 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],
2159 buff[ACTION_SUBTYPE_ID + 1], buff[P2P_PUB_ACTION_SUBTYPE + 1]);
2160 cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, false, GFP_KERNEL);
2166 PRINT_D(GENERIC_DBG, "Rx Frame Type:%x\n", buff[FRAME_TYPE_ID]);
2169 /*Upper layer is informed that the frame is received on this freq*/
2170 s32Freq = ieee80211_channel_to_frequency(u8CurrChannel, IEEE80211_BAND_2GHZ);
2172 if (ieee80211_is_action(buff[FRAME_TYPE_ID])) {
2173 PRINT_D(GENERIC_DBG, "Rx Action Frame Type: %x %x\n", buff[ACTION_SUBTYPE_ID], buff[P2P_PUB_ACTION_SUBTYPE]);
2175 if (priv->bCfgScanning == true && time_after_eq(jiffies, (unsigned long)pstrWFIDrv->u64P2p_MgmtTimeout)) {
2176 PRINT_D(GENERIC_DBG, "Receiving action frames from wrong channels\n");
2179 if (buff[ACTION_CAT_ID] == PUB_ACTION_ATTR_ID) {
2181 switch (buff[ACTION_SUBTYPE_ID]) {
2182 case GAS_INTIAL_REQ:
2183 PRINT_D(GENERIC_DBG, "GAS INITIAL REQ %x\n", buff[ACTION_SUBTYPE_ID]);
2186 case GAS_INTIAL_RSP:
2187 PRINT_D(GENERIC_DBG, "GAS INITIAL RSP %x\n", buff[ACTION_SUBTYPE_ID]);
2190 case PUBLIC_ACT_VENDORSPEC:
2191 /*Now we have a public action vendor specific action frame, check if its a p2p public action frame
2192 * based on the standard its should have the p2p_oui attribute with the following values 50 6f 9A 09*/
2193 if (!memcmp(u8P2P_oui, &buff[ACTION_SUBTYPE_ID + 1], 4)) {
2194 if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP)) {
2196 for (i = P2P_PUB_ACTION_SUBTYPE; i < size; i++) {
2197 if (!memcmp(u8P2P_vendorspec, &buff[i], 6)) {
2198 u8P2Precvrandom = buff[i + 6];
2200 PRINT_D(GENERIC_DBG, "WILC Vendor specific IE:%02x\n", u8P2Precvrandom);
2206 if (u8P2Plocalrandom > u8P2Precvrandom) {
2207 if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP
2208 || buff[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)) {
2209 for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < size; i++) {
2210 if (buff[i] == P2PELEM_ATTR_ID && !(memcmp(u8P2P_oui, &buff[i + 2], 4))) {
2211 WILC_WFI_CfgParseRxAction(&buff[i + 6], size - (i + 6));
2217 PRINT_D(GENERIC_DBG, "PEER WILL BE GO LocaRand=%02x RecvRand %02x\n", u8P2Plocalrandom, u8P2Precvrandom);
2221 if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP) && (bWilc_ie)) {
2222 PRINT_D(GENERIC_DBG, "Sending P2P to host without extra elemnt\n");
2223 /* extra attribute for sig_dbm: signal strength in mBm, or 0 if unknown */
2224 cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size - 7, 0);
2230 PRINT_D(GENERIC_DBG, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buff[ACTION_SUBTYPE_ID]);
2236 cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size - 7, 0);
2241 * @brief WILC_WFI_mgmt_tx_complete
2242 * @details Returns result of writing mgmt frame to VMM (Tx buffers are freed here)
2244 * transmitting status
2246 * @author Amr Abdelmoghny
2250 static void WILC_WFI_mgmt_tx_complete(void *priv, int status)
2252 struct p2p_mgmt_data *pv_data = (struct p2p_mgmt_data *)priv;
2255 kfree(pv_data->buff);
2260 * @brief WILC_WFI_RemainOnChannelReady
2261 * @details Callback function, called from handle_remain_on_channel on being ready on channel
2264 * @author Amr abdelmoghny
2269 static void WILC_WFI_RemainOnChannelReady(void *pUserVoid)
2271 struct wilc_priv *priv;
2273 priv = (struct wilc_priv *)pUserVoid;
2275 PRINT_D(HOSTINF_DBG, "Remain on channel ready\n");
2277 priv->bInP2PlistenState = true;
2279 cfg80211_ready_on_channel(priv->wdev,
2280 priv->strRemainOnChanParams.u64ListenCookie,
2281 priv->strRemainOnChanParams.pstrListenChan,
2282 priv->strRemainOnChanParams.u32ListenDuration,
2287 * @brief WILC_WFI_RemainOnChannelExpired
2288 * @details Callback function, called on expiration of remain-on-channel duration
2291 * @author Amr abdelmoghny
2296 static void WILC_WFI_RemainOnChannelExpired(void *pUserVoid, u32 u32SessionID)
2298 struct wilc_priv *priv;
2300 priv = (struct wilc_priv *)pUserVoid;
2303 if (u32SessionID == priv->strRemainOnChanParams.u32ListenSessionID) {
2304 PRINT_D(GENERIC_DBG, "Remain on channel expired\n");
2306 priv->bInP2PlistenState = false;
2308 /*Inform wpas of remain-on-channel expiration*/
2309 cfg80211_remain_on_channel_expired(priv->wdev,
2310 priv->strRemainOnChanParams.u64ListenCookie,
2311 priv->strRemainOnChanParams.pstrListenChan,
2314 PRINT_D(GENERIC_DBG, "Received ID 0x%x Expected ID 0x%x (No match)\n", u32SessionID
2315 , priv->strRemainOnChanParams.u32ListenSessionID);
2321 * @brief remain_on_channel
2322 * @details Request the driver to remain awake on the specified
2323 * channel for the specified duration to complete an off-channel
2324 * operation (e.g., public action frame exchange). When the driver is
2325 * ready on the requested channel, it must indicate this with an event
2326 * notification by calling cfg80211_ready_on_channel().
2328 * @return int : Return 0 on Success
2333 static int remain_on_channel(struct wiphy *wiphy,
2334 struct wireless_dev *wdev,
2335 struct ieee80211_channel *chan,
2336 unsigned int duration, u64 *cookie)
2338 s32 s32Error = WILC_SUCCESS;
2339 struct wilc_priv *priv;
2341 priv = wiphy_priv(wiphy);
2343 PRINT_D(GENERIC_DBG, "Remaining on channel %d\n", chan->hw_value);
2345 /*BugID_4800: if in AP mode, return.*/
2346 /*This check is to handle the situation when user*/
2347 /*requests "create group" during a running scan*/
2349 if (wdev->iftype == NL80211_IFTYPE_AP) {
2350 PRINT_D(GENERIC_DBG, "Required remain-on-channel while in AP mode");
2354 u8CurrChannel = chan->hw_value;
2356 /*Setting params needed by WILC_WFI_RemainOnChannelExpired()*/
2357 priv->strRemainOnChanParams.pstrListenChan = chan;
2358 priv->strRemainOnChanParams.u64ListenCookie = *cookie;
2359 priv->strRemainOnChanParams.u32ListenDuration = duration;
2360 priv->strRemainOnChanParams.u32ListenSessionID++;
2362 s32Error = host_int_remain_on_channel(priv->hWILCWFIDrv
2363 , priv->strRemainOnChanParams.u32ListenSessionID
2366 , WILC_WFI_RemainOnChannelExpired
2367 , WILC_WFI_RemainOnChannelReady
2374 * @brief cancel_remain_on_channel
2375 * @details Cancel an on-going remain-on-channel operation.
2376 * This allows the operation to be terminated prior to timeout based on
2377 * the duration value.
2378 * @param[in] struct wiphy *wiphy,
2379 * @param[in] struct net_device *dev
2380 * @param[in] u64 cookie,
2381 * @return int : Return 0 on Success
2386 static int cancel_remain_on_channel(struct wiphy *wiphy,
2387 struct wireless_dev *wdev,
2390 s32 s32Error = WILC_SUCCESS;
2391 struct wilc_priv *priv;
2393 priv = wiphy_priv(wiphy);
2395 PRINT_D(CFG80211_DBG, "Cancel remain on channel\n");
2397 s32Error = host_int_ListenStateExpired(priv->hWILCWFIDrv, priv->strRemainOnChanParams.u32ListenSessionID);
2401 * @brief WILC_WFI_add_wilcvendorspec
2402 * @details Adding WILC information elemet to allow two WILC devices to
2403 * identify each other and connect
2404 * @param[in] u8 * buf
2410 void WILC_WFI_add_wilcvendorspec(u8 *buff)
2412 memcpy(buff, u8P2P_vendorspec, sizeof(u8P2P_vendorspec));
2415 * @brief WILC_WFI_mgmt_tx_frame
2424 extern linux_wlan_t *g_linux_wlan;
2425 extern bool bEnablePS;
2426 int mgmt_tx(struct wiphy *wiphy,
2427 struct wireless_dev *wdev,
2428 struct cfg80211_mgmt_tx_params *params,
2431 struct ieee80211_channel *chan = params->chan;
2432 unsigned int wait = params->wait;
2433 const u8 *buf = params->buf;
2434 size_t len = params->len;
2435 const struct ieee80211_mgmt *mgmt;
2436 struct p2p_mgmt_data *mgmt_tx;
2437 struct wilc_priv *priv;
2438 s32 s32Error = WILC_SUCCESS;
2439 tstrWILC_WFIDrv *pstrWFIDrv;
2441 perInterface_wlan_t *nic;
2442 u32 buf_len = len + sizeof(u8P2P_vendorspec) + sizeof(u8P2Plocalrandom);
2444 nic = netdev_priv(wdev->netdev);
2445 priv = wiphy_priv(wiphy);
2446 pstrWFIDrv = (tstrWILC_WFIDrv *)priv->hWILCWFIDrv;
2448 *cookie = (unsigned long)buf;
2449 priv->u64tx_cookie = *cookie;
2450 mgmt = (const struct ieee80211_mgmt *) buf;
2452 if (ieee80211_is_mgmt(mgmt->frame_control)) {
2454 /*mgmt frame allocation*/
2455 mgmt_tx = kmalloc(sizeof(struct p2p_mgmt_data), GFP_KERNEL);
2456 if (mgmt_tx == NULL) {
2457 PRINT_ER("Failed to allocate memory for mgmt_tx structure\n");
2460 mgmt_tx->buff = kmalloc(buf_len, GFP_KERNEL);
2461 if (mgmt_tx->buff == NULL) {
2462 PRINT_ER("Failed to allocate memory for mgmt_tx buff\n");
2466 memcpy(mgmt_tx->buff, buf, len);
2467 mgmt_tx->size = len;
2470 if (ieee80211_is_probe_resp(mgmt->frame_control)) {
2471 PRINT_D(GENERIC_DBG, "TX: Probe Response\n");
2472 PRINT_D(GENERIC_DBG, "Setting channel: %d\n", chan->hw_value);
2473 host_int_set_mac_chnl_num(priv->hWILCWFIDrv, chan->hw_value);
2474 /*Save the current channel after we tune to it*/
2475 u8CurrChannel = chan->hw_value;
2476 } else if (ieee80211_is_action(mgmt->frame_control)) {
2477 PRINT_D(GENERIC_DBG, "ACTION FRAME:%x\n", (u16)mgmt->frame_control);
2481 if (buf[ACTION_CAT_ID] == PUB_ACTION_ATTR_ID) {
2483 /*Only set the channel, if not a negotiation confirmation frame
2484 * (If Negotiation confirmation frame, force it
2485 * to be transmitted on the same negotiation channel)*/
2487 if (buf[ACTION_SUBTYPE_ID] != PUBLIC_ACT_VENDORSPEC ||
2488 buf[P2P_PUB_ACTION_SUBTYPE] != GO_NEG_CONF) {
2489 PRINT_D(GENERIC_DBG, "Setting channel: %d\n", chan->hw_value);
2490 host_int_set_mac_chnl_num(priv->hWILCWFIDrv, chan->hw_value);
2491 /*Save the current channel after we tune to it*/
2492 u8CurrChannel = chan->hw_value;
2494 switch (buf[ACTION_SUBTYPE_ID]) {
2495 case GAS_INTIAL_REQ:
2497 PRINT_D(GENERIC_DBG, "GAS INITIAL REQ %x\n", buf[ACTION_SUBTYPE_ID]);
2501 case GAS_INTIAL_RSP:
2503 PRINT_D(GENERIC_DBG, "GAS INITIAL RSP %x\n", buf[ACTION_SUBTYPE_ID]);
2507 case PUBLIC_ACT_VENDORSPEC:
2509 /*Now we have a public action vendor specific action frame, check if its a p2p public action frame
2510 * based on the standard its should have the p2p_oui attribute with the following values 50 6f 9A 09*/
2511 if (!memcmp(u8P2P_oui, &buf[ACTION_SUBTYPE_ID + 1], 4)) {
2512 /*For the connection of two WILC's connection generate a rand number to determine who will be a GO*/
2513 if ((buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP)) {
2514 if (u8P2Plocalrandom == 1 && u8P2Precvrandom < u8P2Plocalrandom) {
2515 get_random_bytes(&u8P2Plocalrandom, 1);
2516 /*Increment the number to prevent if its 0*/
2521 if ((buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP
2522 || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)) {
2523 if (u8P2Plocalrandom > u8P2Precvrandom) {
2524 PRINT_D(GENERIC_DBG, "LOCAL WILL BE GO LocaRand=%02x RecvRand %02x\n", u8P2Plocalrandom, u8P2Precvrandom);
2526 /*Search for the p2p information information element , after the Public action subtype theres a byte for teh dialog token, skip that*/
2527 for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < len; i++) {
2528 if (buf[i] == P2PELEM_ATTR_ID && !(memcmp(u8P2P_oui, &buf[i + 2], 4))) {
2529 if (buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)
2530 WILC_WFI_CfgParseTxAction(&mgmt_tx->buff[i + 6], len - (i + 6), true, nic->iftype);
2533 /*If using supplicant go intent, no need at all*/
2534 /*to parse transmitted negotiation frames*/
2536 WILC_WFI_CfgParseTxAction(&mgmt_tx->buff[i + 6], len - (i + 6), false, nic->iftype);
2541 if (buf[P2P_PUB_ACTION_SUBTYPE] != P2P_INV_REQ && buf[P2P_PUB_ACTION_SUBTYPE] != P2P_INV_RSP) {
2542 WILC_WFI_add_wilcvendorspec(&mgmt_tx->buff[len]);
2543 mgmt_tx->buff[len + sizeof(u8P2P_vendorspec)] = u8P2Plocalrandom;
2544 mgmt_tx->size = buf_len;
2547 PRINT_D(GENERIC_DBG, "PEER WILL BE GO LocaRand=%02x RecvRand %02x\n", u8P2Plocalrandom, u8P2Precvrandom);
2551 PRINT_D(GENERIC_DBG, "Not a P2P public action frame\n");
2559 PRINT_D(GENERIC_DBG, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buf[ACTION_SUBTYPE_ID]);
2566 PRINT_D(GENERIC_DBG, "TX: ACTION FRAME Type:%x : Chan:%d\n", buf[ACTION_SUBTYPE_ID], chan->hw_value);
2567 pstrWFIDrv->u64P2p_MgmtTimeout = (jiffies + msecs_to_jiffies(wait));
2569 PRINT_D(GENERIC_DBG, "Current Jiffies: %lu Timeout:%llu\n", jiffies, pstrWFIDrv->u64P2p_MgmtTimeout);
2573 g_linux_wlan->oup.wlan_add_mgmt_to_tx_que(mgmt_tx, mgmt_tx->buff, mgmt_tx->size, WILC_WFI_mgmt_tx_complete);
2575 PRINT_D(GENERIC_DBG, "This function transmits only management frames\n");
2580 int mgmt_tx_cancel_wait(struct wiphy *wiphy,
2581 struct wireless_dev *wdev,
2584 struct wilc_priv *priv;
2585 tstrWILC_WFIDrv *pstrWFIDrv;
2587 priv = wiphy_priv(wiphy);
2588 pstrWFIDrv = (tstrWILC_WFIDrv *)priv->hWILCWFIDrv;
2591 PRINT_D(GENERIC_DBG, "Tx Cancel wait :%lu\n", jiffies);
2592 pstrWFIDrv->u64P2p_MgmtTimeout = jiffies;
2594 if (priv->bInP2PlistenState == false) {
2595 /* Bug 5504: This is just to avoid connection failure when getting stuck when the supplicant
2596 * considers the driver falsely that it is in Listen state */
2597 cfg80211_remain_on_channel_expired(priv->wdev,
2598 priv->strRemainOnChanParams.u64ListenCookie,
2599 priv->strRemainOnChanParams.pstrListenChan,
2607 * @brief WILC_WFI_frame_register
2608 * @details Notify driver that a management frame type was
2609 * registered. Note that this callback may not sleep, and cannot run
2610 * concurrently with itself.
2617 void WILC_WFI_frame_register(struct wiphy *wiphy,
2618 struct wireless_dev *wdev,
2619 u16 frame_type, bool reg)
2622 struct wilc_priv *priv;
2623 perInterface_wlan_t *nic;
2626 priv = wiphy_priv(wiphy);
2627 nic = netdev_priv(priv->wdev->netdev);
2635 PRINT_D(GENERIC_DBG, "Frame registering Frame Type: %x: Boolean: %d\n", frame_type, reg);
2636 switch (frame_type) {
2639 nic->g_struct_frame_reg[0].frame_type = frame_type;
2640 nic->g_struct_frame_reg[0].reg = reg;
2646 nic->g_struct_frame_reg[1].frame_type = frame_type;
2647 nic->g_struct_frame_reg[1].reg = reg;
2657 /*If mac is closed, then return*/
2658 if (!g_linux_wlan->wilc1000_initialized) {
2659 PRINT_D(GENERIC_DBG, "Return since mac is closed\n");
2662 host_int_frame_register(priv->hWILCWFIDrv, frame_type, reg);
2669 * @brief WILC_WFI_set_cqm_rssi_config
2670 * @details Configure connection quality monitor RSSI threshold.
2671 * @param[in] struct wiphy *wiphy:
2672 * @param[in] struct net_device *dev:
2673 * @param[in] s32 rssi_thold:
2674 * @param[in] u32 rssi_hyst:
2675 * @return int : Return 0 on Success
2680 static int WILC_WFI_set_cqm_rssi_config(struct wiphy *wiphy,
2681 struct net_device *dev, s32 rssi_thold, u32 rssi_hyst)
2683 PRINT_D(CFG80211_DBG, "Setting CQM RSSi Function\n");
2688 * @brief dump_station
2689 * @details Configure connection quality monitor RSSI threshold.
2690 * @param[in] struct wiphy *wiphy:
2691 * @param[in] struct net_device *dev
2692 * @param[in] int idx
2693 * @param[in] u8 *mac
2694 * @param[in] struct station_info *sinfo
2695 * @return int : Return 0 on Success
2700 static int dump_station(struct wiphy *wiphy, struct net_device *dev,
2701 int idx, u8 *mac, struct station_info *sinfo)
2703 struct wilc_priv *priv;
2705 PRINT_D(CFG80211_DBG, "Dumping station information\n");
2710 priv = wiphy_priv(wiphy);
2712 sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
2714 host_int_get_rssi(priv->hWILCWFIDrv, &(sinfo->signal));
2722 * @brief WILC_WFI_set_power_mgmt
2725 * @return int : Return 0 on Success.
2728 * @version 1.0WILC_WFI_set_cqmWILC_WFI_set_cqm_rssi_configWILC_WFI_set_cqm_rssi_configWILC_WFI_set_cqm_rssi_configWILC_WFI_set_cqm_rssi_config_rssi_config
2730 int WILC_WFI_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
2731 bool enabled, int timeout)
2733 struct wilc_priv *priv;
2735 PRINT_D(CFG80211_DBG, " Power save Enabled= %d , TimeOut = %d\n", enabled, timeout);
2740 priv = wiphy_priv(wiphy);
2741 if (priv->hWILCWFIDrv == NULL) {
2742 PRINT_ER("Driver is NULL\n");
2747 host_int_set_power_mgmt(priv->hWILCWFIDrv, enabled, timeout);
2750 return WILC_SUCCESS;
2753 #ifdef WILC_AP_EXTERNAL_MLME
2755 * @brief change_virtual_intf
2756 * @details Change type/configuration of virtual interface,
2757 * keep the struct wireless_dev's iftype updated.
2759 * @return int : Return 0 on Success.
2764 void wilc1000_wlan_deinit(linux_wlan_t *nic);
2765 int wilc1000_wlan_init(struct net_device *dev, perInterface_wlan_t *p_nic);
2767 static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
2768 enum nl80211_iftype type, u32 *flags, struct vif_params *params)
2770 s32 s32Error = WILC_SUCCESS;
2771 struct wilc_priv *priv;
2772 perInterface_wlan_t *nic;
2779 nic = netdev_priv(dev);
2780 priv = wiphy_priv(wiphy);
2782 PRINT_D(HOSTAPD_DBG, "In Change virtual interface function\n");
2783 PRINT_D(HOSTAPD_DBG, "Wireless interface name =%s\n", dev->name);
2784 u8P2Plocalrandom = 0x01;
2785 u8P2Precvrandom = 0x00;
2789 #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
2790 g_obtainingIP = false;
2791 del_timer(&hDuringIpTimer);
2792 PRINT_D(GENERIC_DBG, "Changing virtual interface, enable scan\n");
2795 /*Set WILC_CHANGING_VIR_IF register to disallow adding futrue keys to CE H/W*/
2796 if (g_ptk_keys_saved && g_gtk_keys_saved) {
2797 Set_machw_change_vir_if(true);
2801 case NL80211_IFTYPE_STATION:
2803 PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_STATION\n");
2805 /* send delba over wlan interface */
2808 dev->ieee80211_ptr->iftype = type;
2809 priv->wdev->iftype = type;
2810 nic->monitor_flag = 0;
2811 nic->iftype = STATION_MODE;
2813 /*Remove the enteries of the previously connected clients*/
2814 memset(priv->assoc_stainfo.au8Sta_AssociatedBss, 0, MAX_NUM_STA * ETH_ALEN);
2816 interface_type = nic->iftype;
2817 nic->iftype = STATION_MODE;
2819 if (g_linux_wlan->wilc1000_initialized) {
2820 host_int_del_All_Rx_BASession(priv->hWILCWFIDrv, g_linux_wlan->strInterfaceInfo[0].aBSSID, TID);
2821 /* ensure that the message Q is empty */
2822 host_int_wait_msg_queue_idle();
2825 /*Eliminate host interface blocking state*/
2826 up(&g_linux_wlan->cfg_event);
2828 wilc1000_wlan_deinit(g_linux_wlan);
2829 wilc1000_wlan_init(dev, nic);
2830 g_wilc_initialized = 1;
2831 nic->iftype = interface_type;
2833 /*Setting interface 1 drv handler and mac address in newly downloaded FW*/
2834 host_int_set_wfi_drv_handler(g_linux_wlan->strInterfaceInfo[0].drvHandler);
2835 host_int_set_MacAddress(g_linux_wlan->strInterfaceInfo[0].drvHandler,
2836 g_linux_wlan->strInterfaceInfo[0].aSrcAddress);
2837 host_int_set_operation_mode(priv->hWILCWFIDrv, STATION_MODE);
2839 /*Add saved WEP keys, if any*/
2840 if (g_wep_keys_saved) {
2841 host_int_set_WEPDefaultKeyID(g_linux_wlan->strInterfaceInfo[0].drvHandler,
2842 g_key_wep_params.key_idx);
2843 host_int_add_wep_key_bss_sta(g_linux_wlan->strInterfaceInfo[0].drvHandler,
2844 g_key_wep_params.key,
2845 g_key_wep_params.key_len,
2846 g_key_wep_params.key_idx);
2849 /*No matter the driver handler passed here, it will be overwriiten*/
2850 /*in Handle_FlushConnect() with gu8FlushedJoinReqDrvHandler*/
2851 host_int_flush_join_req(priv->hWILCWFIDrv);
2853 /*Add saved PTK and GTK keys, if any*/
2854 if (g_ptk_keys_saved && g_gtk_keys_saved) {
2855 PRINT_D(CFG80211_DBG, "ptk %x %x %x\n", g_key_ptk_params.key[0],
2856 g_key_ptk_params.key[1],
2857 g_key_ptk_params.key[2]);
2858 PRINT_D(CFG80211_DBG, "gtk %x %x %x\n", g_key_gtk_params.key[0],
2859 g_key_gtk_params.key[1],
2860 g_key_gtk_params.key[2]);
2861 add_key(g_linux_wlan->strInterfaceInfo[0].wilc_netdev->ieee80211_ptr->wiphy,
2862 g_linux_wlan->strInterfaceInfo[0].wilc_netdev,
2863 g_add_ptk_key_params.key_idx,
2864 g_add_ptk_key_params.pairwise,
2865 g_add_ptk_key_params.mac_addr,
2866 (struct key_params *)(&g_key_ptk_params));
2868 add_key(g_linux_wlan->strInterfaceInfo[0].wilc_netdev->ieee80211_ptr->wiphy,
2869 g_linux_wlan->strInterfaceInfo[0].wilc_netdev,
2870 g_add_gtk_key_params.key_idx,
2871 g_add_gtk_key_params.pairwise,
2872 g_add_gtk_key_params.mac_addr,
2873 (struct key_params *)(&g_key_gtk_params));
2876 /*BugID_4847: registered frames in firmware are now*/
2877 /*lost due to mac close. So re-register those frames*/
2878 if (g_linux_wlan->wilc1000_initialized) {
2879 for (i = 0; i < num_reg_frame; i++) {
2880 PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", nic->g_struct_frame_reg[i].frame_type,
2881 nic->g_struct_frame_reg[i].reg);
2882 host_int_frame_register(priv->hWILCWFIDrv,
2883 nic->g_struct_frame_reg[i].frame_type,
2884 nic->g_struct_frame_reg[i].reg);
2889 host_int_set_power_mgmt(priv->hWILCWFIDrv, 1, 0);
2894 case NL80211_IFTYPE_P2P_CLIENT:
2896 host_int_set_power_mgmt(priv->hWILCWFIDrv, 0, 0);
2898 PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_P2P_CLIENT\n");
2900 host_int_del_All_Rx_BASession(priv->hWILCWFIDrv, g_linux_wlan->strInterfaceInfo[0].aBSSID, TID);
2902 dev->ieee80211_ptr->iftype = type;
2903 priv->wdev->iftype = type;
2904 nic->monitor_flag = 0;
2908 PRINT_D(HOSTAPD_DBG, "Downloading P2P_CONCURRENCY_FIRMWARE\n");
2909 nic->iftype = CLIENT_MODE;
2912 if (g_linux_wlan->wilc1000_initialized) {
2913 /* ensure that the message Q is empty */
2914 host_int_wait_msg_queue_idle();
2916 wilc1000_wlan_deinit(g_linux_wlan);
2917 wilc1000_wlan_init(dev, nic);
2918 g_wilc_initialized = 1;
2920 host_int_set_wfi_drv_handler(g_linux_wlan->strInterfaceInfo[0].drvHandler);
2921 host_int_set_MacAddress(g_linux_wlan->strInterfaceInfo[0].drvHandler,
2922 g_linux_wlan->strInterfaceInfo[0].aSrcAddress);
2923 host_int_set_operation_mode(priv->hWILCWFIDrv, STATION_MODE);
2925 /*Add saved WEP keys, if any*/
2926 if (g_wep_keys_saved) {
2927 host_int_set_WEPDefaultKeyID(g_linux_wlan->strInterfaceInfo[0].drvHandler,
2928 g_key_wep_params.key_idx);
2929 host_int_add_wep_key_bss_sta(g_linux_wlan->strInterfaceInfo[0].drvHandler,
2930 g_key_wep_params.key,
2931 g_key_wep_params.key_len,
2932 g_key_wep_params.key_idx);
2935 /*No matter the driver handler passed here, it will be overwriiten*/
2936 /*in Handle_FlushConnect() with gu8FlushedJoinReqDrvHandler*/
2937 host_int_flush_join_req(priv->hWILCWFIDrv);
2939 /*Add saved PTK and GTK keys, if any*/
2940 if (g_ptk_keys_saved && g_gtk_keys_saved) {
2941 PRINT_D(CFG80211_DBG, "ptk %x %x %x\n", g_key_ptk_params.key[0],
2942 g_key_ptk_params.key[1],
2943 g_key_ptk_params.key[2]);
2944 PRINT_D(CFG80211_DBG, "gtk %x %x %x\n", g_key_gtk_params.key[0],
2945 g_key_gtk_params.key[1],
2946 g_key_gtk_params.key[2]);
2947 add_key(g_linux_wlan->strInterfaceInfo[0].wilc_netdev->ieee80211_ptr->wiphy,
2948 g_linux_wlan->strInterfaceInfo[0].wilc_netdev,
2949 g_add_ptk_key_params.key_idx,
2950 g_add_ptk_key_params.pairwise,
2951 g_add_ptk_key_params.mac_addr,
2952 (struct key_params *)(&g_key_ptk_params));
2954 add_key(g_linux_wlan->strInterfaceInfo[0].wilc_netdev->ieee80211_ptr->wiphy,
2955 g_linux_wlan->strInterfaceInfo[0].wilc_netdev,
2956 g_add_gtk_key_params.key_idx,
2957 g_add_gtk_key_params.pairwise,
2958 g_add_gtk_key_params.mac_addr,
2959 (struct key_params *)(&g_key_gtk_params));
2962 /*Refresh scan, to refresh the scan results to the wpa_supplicant. Set MachHw to false to enable further key installments*/
2963 refresh_scan(priv, 1, true);
2964 Set_machw_change_vir_if(false);
2966 /*BugID_4847: registered frames in firmware are now lost
2967 * due to mac close. So re-register those frames */
2968 if (g_linux_wlan->wilc1000_initialized) {
2969 for (i = 0; i < num_reg_frame; i++) {
2970 PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", nic->g_struct_frame_reg[i].frame_type,
2971 nic->g_struct_frame_reg[i].reg);
2972 host_int_frame_register(priv->hWILCWFIDrv,
2973 nic->g_struct_frame_reg[i].frame_type,
2974 nic->g_struct_frame_reg[i].reg);
2981 case NL80211_IFTYPE_AP:
2983 PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_AP %d\n", type);
2984 dev->ieee80211_ptr->iftype = type;
2985 priv->wdev->iftype = type;
2986 nic->iftype = AP_MODE;
2987 PRINT_D(CORECONFIG_DBG, "priv->hWILCWFIDrv[%p]\n", priv->hWILCWFIDrv);
2989 PRINT_D(HOSTAPD_DBG, "Downloading AP firmware\n");
2990 linux_wlan_get_firmware(nic);
2992 /*If wilc is running, then close-open to actually get new firmware running (serves P2P)*/
2993 if (g_linux_wlan->wilc1000_initialized) {
2994 nic->iftype = AP_MODE;
2995 g_linux_wlan->wilc1000_initialized = 1;
2999 /*BugID_4847: registered frames in firmware are now lost
3000 * due to mac close. So re-register those frames */
3001 for (i = 0; i < num_reg_frame; i++) {
3002 PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", nic->g_struct_frame_reg[i].frame_type,
3003 nic->g_struct_frame_reg[i].reg);
3004 host_int_frame_register(priv->hWILCWFIDrv,
3005 nic->g_struct_frame_reg[i].frame_type,
3006 nic->g_struct_frame_reg[i].reg);
3012 case NL80211_IFTYPE_P2P_GO:
3013 PRINT_D(GENERIC_DBG, "start duringIP timer\n");
3015 #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
3016 g_obtainingIP = true;
3017 mod_timer(&hDuringIpTimer, jiffies + msecs_to_jiffies(duringIP_TIME));
3019 host_int_set_power_mgmt(priv->hWILCWFIDrv, 0, 0);
3021 /*Delete block ack has to be the latest config packet*/
3022 /*sent before downloading new FW. This is because it blocks on*/
3023 /*hWaitResponse semaphore, which allows previous config*/
3024 /*packets to actually take action on old FW*/
3025 host_int_del_All_Rx_BASession(priv->hWILCWFIDrv, g_linux_wlan->strInterfaceInfo[0].aBSSID, TID);
3027 PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_GO\n");
3028 dev->ieee80211_ptr->iftype = type;
3029 priv->wdev->iftype = type;
3031 PRINT_D(CORECONFIG_DBG, "priv->hWILCWFIDrv[%p]\n", priv->hWILCWFIDrv);
3034 PRINT_D(HOSTAPD_DBG, "Downloading P2P_CONCURRENCY_FIRMWARE\n");
3038 nic->iftype = GO_MODE;
3040 /* ensure that the message Q is empty */
3041 host_int_wait_msg_queue_idle();
3042 wilc1000_wlan_deinit(g_linux_wlan);
3043 wilc1000_wlan_init(dev, nic);
3044 g_wilc_initialized = 1;
3047 /*Setting interface 1 drv handler and mac address in newly downloaded FW*/
3048 host_int_set_wfi_drv_handler(g_linux_wlan->strInterfaceInfo[0].drvHandler);
3049 host_int_set_MacAddress(g_linux_wlan->strInterfaceInfo[0].drvHandler,
3050 g_linux_wlan->strInterfaceInfo[0].aSrcAddress);
3051 host_int_set_operation_mode(priv->hWILCWFIDrv, AP_MODE);
3053 /*Add saved WEP keys, if any*/
3054 if (g_wep_keys_saved) {
3055 host_int_set_WEPDefaultKeyID(g_linux_wlan->strInterfaceInfo[0].drvHandler,
3056 g_key_wep_params.key_idx);
3057 host_int_add_wep_key_bss_sta(g_linux_wlan->strInterfaceInfo[0].drvHandler,
3058 g_key_wep_params.key,
3059 g_key_wep_params.key_len,
3060 g_key_wep_params.key_idx);
3063 /*No matter the driver handler passed here, it will be overwriiten*/
3064 /*in Handle_FlushConnect() with gu8FlushedJoinReqDrvHandler*/
3065 host_int_flush_join_req(priv->hWILCWFIDrv);
3067 /*Add saved PTK and GTK keys, if any*/
3068 if (g_ptk_keys_saved && g_gtk_keys_saved) {
3069 PRINT_D(CFG80211_DBG, "ptk %x %x %x cipher %x\n", g_key_ptk_params.key[0],
3070 g_key_ptk_params.key[1],
3071 g_key_ptk_params.key[2],
3072 g_key_ptk_params.cipher);
3073 PRINT_D(CFG80211_DBG, "gtk %x %x %x cipher %x\n", g_key_gtk_params.key[0],
3074 g_key_gtk_params.key[1],
3075 g_key_gtk_params.key[2],
3076 g_key_gtk_params.cipher);
3078 add_key(g_linux_wlan->strInterfaceInfo[0].wilc_netdev->ieee80211_ptr->wiphy,
3079 g_linux_wlan->strInterfaceInfo[0].wilc_netdev,
3080 g_add_ptk_key_params.key_idx,
3081 g_add_ptk_key_params.pairwise,
3082 g_add_ptk_key_params.mac_addr,
3083 (struct key_params *)(&g_key_ptk_params));
3085 add_key(g_linux_wlan->strInterfaceInfo[0].wilc_netdev->ieee80211_ptr->wiphy,
3086 g_linux_wlan->strInterfaceInfo[0].wilc_netdev,
3087 g_add_gtk_key_params.key_idx,
3088 g_add_gtk_key_params.pairwise,
3089 g_add_gtk_key_params.mac_addr,
3090 (struct key_params *)(&g_key_gtk_params));
3095 /*BugID_4847: registered frames in firmware are now*/
3096 /*lost due to mac close. So re-register those frames*/
3097 if (g_linux_wlan->wilc1000_initialized) {
3098 for (i = 0; i < num_reg_frame; i++) {
3099 PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", nic->g_struct_frame_reg[i].frame_type,
3100 nic->g_struct_frame_reg[i].reg);
3101 host_int_frame_register(priv->hWILCWFIDrv,
3102 nic->g_struct_frame_reg[i].frame_type,
3103 nic->g_struct_frame_reg[i].reg);
3110 PRINT_ER("Unknown interface type= %d\n", type);
3119 /* (austin.2013-07-23)
3121 * To support revised cfg80211_ops
3123 * add_beacon --> start_ap
3124 * set_beacon --> change_beacon
3125 * del_beacon --> stop_ap
3127 * beacon_parameters --> cfg80211_ap_settings
3128 * cfg80211_beacon_data
3130 * applicable for linux kernel 3.4+
3135 * @details Add a beacon with given parameters, @head, @interval
3136 * and @dtim_period will be valid, @tail is optional.
3138 * @param[in] dev The net device structure
3139 * @param[in] settings cfg80211_ap_settings parameters for the beacon to be added
3140 * @return int : Return 0 on Success.
3145 static int start_ap(struct wiphy *wiphy, struct net_device *dev,
3146 struct cfg80211_ap_settings *settings)
3148 struct cfg80211_beacon_data *beacon = &(settings->beacon);
3149 struct wilc_priv *priv;
3150 s32 s32Error = WILC_SUCCESS;
3152 priv = wiphy_priv(wiphy);
3153 PRINT_D(HOSTAPD_DBG, "Starting ap\n");
3155 PRINT_D(HOSTAPD_DBG, "Interval = %d\n DTIM period = %d\n Head length = %zu Tail length = %zu\n",
3156 settings->beacon_interval, settings->dtim_period, beacon->head_len, beacon->tail_len);
3158 s32Error = set_channel(wiphy, &settings->chandef);
3160 if (s32Error != WILC_SUCCESS)
3161 PRINT_ER("Error in setting channel\n");
3163 linux_wlan_set_bssid(dev, g_linux_wlan->strInterfaceInfo[0].aSrcAddress);
3165 s32Error = host_int_add_beacon(priv->hWILCWFIDrv,
3166 settings->beacon_interval,
3167 settings->dtim_period,
3168 beacon->head_len, (u8 *)beacon->head,
3169 beacon->tail_len, (u8 *)beacon->tail);
3175 * @brief change_beacon
3176 * @details Add a beacon with given parameters, @head, @interval
3177 * and @dtim_period will be valid, @tail is optional.
3179 * @param[in] dev The net device structure
3180 * @param[in] beacon cfg80211_beacon_data for the beacon to be changed
3181 * @return int : Return 0 on Success.
3186 static int change_beacon(struct wiphy *wiphy, struct net_device *dev,
3187 struct cfg80211_beacon_data *beacon)
3189 struct wilc_priv *priv;
3190 s32 s32Error = WILC_SUCCESS;
3192 priv = wiphy_priv(wiphy);
3193 PRINT_D(HOSTAPD_DBG, "Setting beacon\n");
3196 s32Error = host_int_add_beacon(priv->hWILCWFIDrv,
3199 beacon->head_len, (u8 *)beacon->head,
3200 beacon->tail_len, (u8 *)beacon->tail);
3207 * @details Remove beacon configuration and stop sending the beacon.
3209 * @return int : Return 0 on Success.
3214 static int stop_ap(struct wiphy *wiphy, struct net_device *dev)
3216 s32 s32Error = WILC_SUCCESS;
3217 struct wilc_priv *priv;
3218 u8 NullBssid[ETH_ALEN] = {0};
3221 WILC_NULLCHECK(s32Error, wiphy);
3223 priv = wiphy_priv(wiphy);
3225 PRINT_D(HOSTAPD_DBG, "Deleting beacon\n");
3228 linux_wlan_set_bssid(dev, NullBssid);
3230 s32Error = host_int_del_beacon(priv->hWILCWFIDrv);
3232 WILC_ERRORCHECK(s32Error);
3234 WILC_CATCH(s32Error)
3241 * @brief add_station
3242 * @details Add a new station.
3244 * @return int : Return 0 on Success.
3249 static int add_station(struct wiphy *wiphy, struct net_device *dev,
3250 const u8 *mac, struct station_parameters *params)
3252 s32 s32Error = WILC_SUCCESS;
3253 struct wilc_priv *priv;
3254 tstrWILC_AddStaParam strStaParams = { {0} };
3255 perInterface_wlan_t *nic;
3258 WILC_NULLCHECK(s32Error, wiphy);
3260 priv = wiphy_priv(wiphy);
3261 nic = netdev_priv(dev);
3263 if (nic->iftype == AP_MODE || nic->iftype == GO_MODE) {
3264 memcpy(strStaParams.au8BSSID, mac, ETH_ALEN);
3265 memcpy(priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid], mac, ETH_ALEN);
3266 strStaParams.u16AssocID = params->aid;
3267 strStaParams.u8NumRates = params->supported_rates_len;
3268 strStaParams.pu8Rates = params->supported_rates;
3270 PRINT_D(CFG80211_DBG, "Adding station parameters %d\n", params->aid);
3272 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],
3273 priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][5]);
3274 PRINT_D(HOSTAPD_DBG, "ASSOC ID = %d\n", strStaParams.u16AssocID);
3275 PRINT_D(HOSTAPD_DBG, "Number of supported rates = %d\n", strStaParams.u8NumRates);
3277 if (params->ht_capa == NULL) {
3278 strStaParams.bIsHTSupported = false;
3280 strStaParams.bIsHTSupported = true;
3281 strStaParams.u16HTCapInfo = params->ht_capa->cap_info;
3282 strStaParams.u8AmpduParams = params->ht_capa->ampdu_params_info;
3283 memcpy(strStaParams.au8SuppMCsSet, ¶ms->ht_capa->mcs, WILC_SUPP_MCS_SET_SIZE);
3284 strStaParams.u16HTExtParams = params->ht_capa->extended_ht_cap_info;
3285 strStaParams.u32TxBeamformingCap = params->ht_capa->tx_BF_cap_info;
3286 strStaParams.u8ASELCap = params->ht_capa->antenna_selection_info;
3289 strStaParams.u16FlagsMask = params->sta_flags_mask;
3290 strStaParams.u16FlagsSet = params->sta_flags_set;
3292 PRINT_D(HOSTAPD_DBG, "IS HT supported = %d\n", strStaParams.bIsHTSupported);
3293 PRINT_D(HOSTAPD_DBG, "Capability Info = %d\n", strStaParams.u16HTCapInfo);
3294 PRINT_D(HOSTAPD_DBG, "AMPDU Params = %d\n", strStaParams.u8AmpduParams);
3295 PRINT_D(HOSTAPD_DBG, "HT Extended params = %d\n", strStaParams.u16HTExtParams);
3296 PRINT_D(HOSTAPD_DBG, "Tx Beamforming Cap = %d\n", strStaParams.u32TxBeamformingCap);
3297 PRINT_D(HOSTAPD_DBG, "Antenna selection info = %d\n", strStaParams.u8ASELCap);
3298 PRINT_D(HOSTAPD_DBG, "Flag Mask = %d\n", strStaParams.u16FlagsMask);
3299 PRINT_D(HOSTAPD_DBG, "Flag Set = %d\n", strStaParams.u16FlagsSet);
3301 s32Error = host_int_add_station(priv->hWILCWFIDrv, &strStaParams);
3302 WILC_ERRORCHECK(s32Error);
3305 WILC_CATCH(s32Error)
3312 * @brief del_station
3313 * @details Remove a station; @mac may be NULL to remove all stations.
3315 * @return int : Return 0 on Success.
3320 static int del_station(struct wiphy *wiphy, struct net_device *dev,
3321 struct station_del_parameters *params)
3323 const u8 *mac = params->mac;
3324 s32 s32Error = WILC_SUCCESS;
3325 struct wilc_priv *priv;
3326 perInterface_wlan_t *nic;
3328 WILC_NULLCHECK(s32Error, wiphy);
3330 priv = wiphy_priv(wiphy);
3331 nic = netdev_priv(dev);
3333 if (nic->iftype == AP_MODE || nic->iftype == GO_MODE) {
3334 PRINT_D(HOSTAPD_DBG, "Deleting station\n");
3338 PRINT_D(HOSTAPD_DBG, "All associated stations\n");
3339 s32Error = host_int_del_allstation(priv->hWILCWFIDrv, priv->assoc_stainfo.au8Sta_AssociatedBss);
3341 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]);
3344 s32Error = host_int_del_station(priv->hWILCWFIDrv, mac);
3346 WILC_ERRORCHECK(s32Error);
3348 WILC_CATCH(s32Error)
3355 * @brief change_station
3356 * @details Modify a given station.
3358 * @return int : Return 0 on Success.
3363 static int change_station(struct wiphy *wiphy, struct net_device *dev,
3364 const u8 *mac, struct station_parameters *params)
3366 s32 s32Error = WILC_SUCCESS;
3367 struct wilc_priv *priv;
3368 tstrWILC_AddStaParam strStaParams = { {0} };
3369 perInterface_wlan_t *nic;
3372 PRINT_D(HOSTAPD_DBG, "Change station paramters\n");
3374 WILC_NULLCHECK(s32Error, wiphy);
3376 priv = wiphy_priv(wiphy);
3377 nic = netdev_priv(dev);
3379 if (nic->iftype == AP_MODE || nic->iftype == GO_MODE) {
3380 memcpy(strStaParams.au8BSSID, mac, ETH_ALEN);
3381 strStaParams.u16AssocID = params->aid;
3382 strStaParams.u8NumRates = params->supported_rates_len;
3383 strStaParams.pu8Rates = params->supported_rates;
3385 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],
3386 strStaParams.au8BSSID[5]);
3387 PRINT_D(HOSTAPD_DBG, "ASSOC ID = %d\n", strStaParams.u16AssocID);
3388 PRINT_D(HOSTAPD_DBG, "Number of supported rates = %d\n", strStaParams.u8NumRates);
3390 if (params->ht_capa == NULL) {
3391 strStaParams.bIsHTSupported = false;
3393 strStaParams.bIsHTSupported = true;
3394 strStaParams.u16HTCapInfo = params->ht_capa->cap_info;
3395 strStaParams.u8AmpduParams = params->ht_capa->ampdu_params_info;
3396 memcpy(strStaParams.au8SuppMCsSet, ¶ms->ht_capa->mcs, WILC_SUPP_MCS_SET_SIZE);
3397 strStaParams.u16HTExtParams = params->ht_capa->extended_ht_cap_info;
3398 strStaParams.u32TxBeamformingCap = params->ht_capa->tx_BF_cap_info;
3399 strStaParams.u8ASELCap = params->ht_capa->antenna_selection_info;
3403 strStaParams.u16FlagsMask = params->sta_flags_mask;
3404 strStaParams.u16FlagsSet = params->sta_flags_set;
3406 PRINT_D(HOSTAPD_DBG, "IS HT supported = %d\n", strStaParams.bIsHTSupported);
3407 PRINT_D(HOSTAPD_DBG, "Capability Info = %d\n", strStaParams.u16HTCapInfo);
3408 PRINT_D(HOSTAPD_DBG, "AMPDU Params = %d\n", strStaParams.u8AmpduParams);
3409 PRINT_D(HOSTAPD_DBG, "HT Extended params = %d\n", strStaParams.u16HTExtParams);
3410 PRINT_D(HOSTAPD_DBG, "Tx Beamforming Cap = %d\n", strStaParams.u32TxBeamformingCap);
3411 PRINT_D(HOSTAPD_DBG, "Antenna selection info = %d\n", strStaParams.u8ASELCap);
3412 PRINT_D(HOSTAPD_DBG, "Flag Mask = %d\n", strStaParams.u16FlagsMask);
3413 PRINT_D(HOSTAPD_DBG, "Flag Set = %d\n", strStaParams.u16FlagsSet);
3415 s32Error = host_int_edit_station(priv->hWILCWFIDrv, &strStaParams);
3416 WILC_ERRORCHECK(s32Error);
3418 WILC_CATCH(s32Error)
3426 * @brief add_virtual_intf
3429 * @return int : Return 0 on Success.
3434 struct wireless_dev *add_virtual_intf(struct wiphy *wiphy, const char *name,
3435 unsigned char name_assign_type,
3436 enum nl80211_iftype type, u32 *flags,
3437 struct vif_params *params)
3439 perInterface_wlan_t *nic;
3440 struct wilc_priv *priv;
3441 struct net_device *new_ifc = NULL;
3443 priv = wiphy_priv(wiphy);
3447 PRINT_D(HOSTAPD_DBG, "Adding monitor interface[%p]\n", priv->wdev->netdev);
3449 nic = netdev_priv(priv->wdev->netdev);
3452 if (type == NL80211_IFTYPE_MONITOR) {
3453 PRINT_D(HOSTAPD_DBG, "Monitor interface mode: Initializing mon interface virtual device driver\n");
3454 PRINT_D(HOSTAPD_DBG, "Adding monitor interface[%p]\n", nic->wilc_netdev);
3455 new_ifc = WILC_WFI_init_mon_interface(name, nic->wilc_netdev);
3456 if (new_ifc != NULL) {
3457 PRINT_D(HOSTAPD_DBG, "Setting monitor flag in private structure\n");
3458 nic = netdev_priv(priv->wdev->netdev);
3459 nic->monitor_flag = 1;
3461 PRINT_ER("Error in initializing monitor interface\n ");
3467 * @brief del_virtual_intf
3470 * @return int : Return 0 on Success.
3475 int del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) /* tony for v3.8 support */
3477 PRINT_D(HOSTAPD_DBG, "Deleting virtual interface\n");
3478 return WILC_SUCCESS;
3483 #endif /*WILC_AP_EXTERNAL_MLME*/
3484 static struct cfg80211_ops wilc_cfg80211_ops = {
3486 .set_monitor_channel = set_channel,
3489 .disconnect = disconnect,
3493 .set_default_key = set_default_key,
3494 #ifdef WILC_AP_EXTERNAL_MLME
3495 .add_virtual_intf = add_virtual_intf,
3496 .del_virtual_intf = del_virtual_intf,
3497 .change_virtual_intf = change_virtual_intf,
3499 .start_ap = start_ap,
3500 .change_beacon = change_beacon,
3502 .add_station = add_station,
3503 .del_station = del_station,
3504 .change_station = change_station,
3505 #endif /* WILC_AP_EXTERNAL_MLME*/
3506 .get_station = get_station,
3507 .dump_station = dump_station,
3508 .change_bss = change_bss,
3509 .set_wiphy_params = set_wiphy_params,
3511 .set_pmksa = set_pmksa,
3512 .del_pmksa = del_pmksa,
3513 .flush_pmksa = flush_pmksa,
3515 .remain_on_channel = remain_on_channel,
3516 .cancel_remain_on_channel = cancel_remain_on_channel,
3517 .mgmt_tx_cancel_wait = mgmt_tx_cancel_wait,
3519 .mgmt_frame_register = WILC_WFI_frame_register,
3520 .set_power_mgmt = WILC_WFI_set_power_mgmt,
3521 .set_cqm_rssi_config = WILC_WFI_set_cqm_rssi_config,
3531 * @brief WILC_WFI_update_stats
3532 * @details Modify parameters for a given BSS.
3534 * @return int : Return 0 on Success.
3537 * @version 1.0WILC_WFI_set_cqmWILC_WFI_set_cqm_rssi_configWILC_WFI_set_cqm_rssi_configWILC_WFI_set_cqm_rssi_configWILC_WFI_set_cqm_rssi_config_rssi_config
3539 int WILC_WFI_update_stats(struct wiphy *wiphy, u32 pktlen, u8 changed)
3542 struct wilc_priv *priv;
3544 priv = wiphy_priv(wiphy);
3548 case WILC_WFI_RX_PKT:
3550 priv->netstats.rx_packets++;
3551 priv->netstats.rx_bytes += pktlen;
3552 priv->netstats.rx_time = get_jiffies_64();
3556 case WILC_WFI_TX_PKT:
3558 priv->netstats.tx_packets++;
3559 priv->netstats.tx_bytes += pktlen;
3560 priv->netstats.tx_time = get_jiffies_64();
3573 * @brief WILC_WFI_CfgAlloc
3574 * @details Allocation of the wireless device structure and assigning it
3575 * to the cfg80211 operations structure.
3577 * @return wireless_dev : Returns pointer to wireless_dev structure.
3582 struct wireless_dev *WILC_WFI_CfgAlloc(void)
3585 struct wireless_dev *wdev;
3588 PRINT_D(CFG80211_DBG, "Allocating wireless device\n");
3589 /*Allocating the wireless device structure*/
3590 wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
3592 PRINT_ER("Cannot allocate wireless device\n");
3596 /*Creating a new wiphy, linking wireless structure with the wiphy structure*/
3597 wdev->wiphy = wiphy_new(&wilc_cfg80211_ops, sizeof(struct wilc_priv));
3599 PRINT_ER("Cannot allocate wiphy\n");
3604 #ifdef WILC_AP_EXTERNAL_MLME
3605 /* enable 802.11n HT */
3606 WILC_WFI_band_2ghz.ht_cap.ht_supported = 1;
3607 WILC_WFI_band_2ghz.ht_cap.cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
3608 WILC_WFI_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
3609 WILC_WFI_band_2ghz.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K;
3610 WILC_WFI_band_2ghz.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
3614 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &WILC_WFI_band_2ghz;
3625 * @brief WILC_WFI_WiphyRegister
3626 * @details Registering of the wiphy structure and interface modes
3633 struct wireless_dev *WILC_WFI_WiphyRegister(struct net_device *net)
3635 struct wilc_priv *priv;
3636 struct wireless_dev *wdev;
3637 s32 s32Error = WILC_SUCCESS;
3639 PRINT_D(CFG80211_DBG, "Registering wifi device\n");
3641 wdev = WILC_WFI_CfgAlloc();
3643 PRINT_ER("CfgAlloc Failed\n");
3648 /*Return hardware description structure (wiphy)'s priv*/
3649 priv = wdev_priv(wdev);
3650 sema_init(&(priv->SemHandleUpdateStats), 1);
3652 /*Link the wiphy with wireless structure*/
3655 /*Maximum number of probed ssid to be added by user for the scan request*/
3656 wdev->wiphy->max_scan_ssids = MAX_NUM_PROBED_SSID;
3657 /*Maximum number of pmkids to be cashed*/
3658 wdev->wiphy->max_num_pmkids = WILC_MAX_NUM_PMKIDS;
3659 PRINT_INFO(CFG80211_DBG, "Max number of PMKIDs = %d\n", wdev->wiphy->max_num_pmkids);
3661 wdev->wiphy->max_scan_ie_len = 1000;
3663 /*signal strength in mBm (100*dBm) */
3664 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
3666 /*Set the availaible cipher suites*/
3667 wdev->wiphy->cipher_suites = cipher_suites;
3668 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
3669 /*Setting default managment types: for register action frame: */
3670 wdev->wiphy->mgmt_stypes = wilc_wfi_cfg80211_mgmt_types;
3673 wdev->wiphy->max_remain_on_channel_duration = 500;
3674 /*Setting the wiphy interfcae mode and type before registering the wiphy*/
3675 wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR) | BIT(NL80211_IFTYPE_P2P_GO) |
3676 BIT(NL80211_IFTYPE_P2P_CLIENT);
3677 wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
3679 wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR);
3681 wdev->iftype = NL80211_IFTYPE_STATION;
3685 PRINT_INFO(CFG80211_DBG, "Max scan ids = %d,Max scan IE len = %d,Signal Type = %d,Interface Modes = %d,Interface Type = %d\n",
3686 wdev->wiphy->max_scan_ssids, wdev->wiphy->max_scan_ie_len, wdev->wiphy->signal_type,
3687 wdev->wiphy->interface_modes, wdev->iftype);
3690 set_wiphy_dev(wdev->wiphy, &local_sdio_func->dev); /* tony */
3693 /*Register wiphy structure*/
3694 s32Error = wiphy_register(wdev->wiphy);
3696 PRINT_ER("Cannot register wiphy device\n");
3697 /*should define what action to be taken in such failure*/
3699 PRINT_D(CFG80211_DBG, "Successful Registering\n");
3708 * @brief WILC_WFI_WiphyFree
3709 * @details Freeing allocation of the wireless device structure
3716 int WILC_WFI_InitHostInt(struct net_device *net)
3719 s32 s32Error = WILC_SUCCESS;
3721 struct wilc_priv *priv;
3723 PRINT_D(INIT_DBG, "Host[%p][%p]\n", net, net->ieee80211_ptr);
3724 priv = wdev_priv(net->ieee80211_ptr);
3726 setup_timer(&hAgingTimer, remove_network_from_shadow, 0);
3727 #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
3728 setup_timer(&hDuringIpTimer, clear_duringIP, 0);
3733 PRINT_ER("Failed to creat refresh Timer\n");
3737 priv->gbAutoRateAdjusted = false;
3739 priv->bInP2PlistenState = false;
3741 sema_init(&(priv->hSemScanReq), 1);
3742 s32Error = host_int_init(&priv->hWILCWFIDrv);
3744 PRINT_ER("Error while initializing hostinterface\n");
3750 * @brief WILC_WFI_WiphyFree
3751 * @details Freeing allocation of the wireless device structure
3758 int WILC_WFI_DeInitHostInt(struct net_device *net)
3760 s32 s32Error = WILC_SUCCESS;
3762 struct wilc_priv *priv;
3764 priv = wdev_priv(net->ieee80211_ptr);
3766 priv->gbAutoRateAdjusted = false;
3768 priv->bInP2PlistenState = false;
3772 s32Error = host_int_deinit(priv->hWILCWFIDrv);
3774 /* Clear the Shadow scan */
3775 clear_shadow_scan(priv);
3776 #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
3778 PRINT_D(CORECONFIG_DBG, "destroy during ip\n");
3779 del_timer_sync(&hDuringIpTimer);
3784 PRINT_ER("Error while deintializing host interface\n");
3791 * @brief WILC_WFI_WiphyFree
3792 * @details Freeing allocation of the wireless device structure
3799 void WILC_WFI_WiphyFree(struct net_device *net)
3802 PRINT_D(CFG80211_DBG, "Unregistering wiphy\n");
3805 PRINT_D(INIT_DBG, "net_device is NULL\n");
3809 if (net->ieee80211_ptr == NULL) {
3810 PRINT_D(INIT_DBG, "ieee80211_ptr is NULL\n");
3814 if (net->ieee80211_ptr->wiphy == NULL) {
3815 PRINT_D(INIT_DBG, "wiphy is NULL\n");
3819 wiphy_unregister(net->ieee80211_ptr->wiphy);
3821 PRINT_D(INIT_DBG, "Freeing wiphy\n");
3822 wiphy_free(net->ieee80211_ptr->wiphy);
3823 kfree(net->ieee80211_ptr);