static void ar6000_wow_resume(AR_SOFTC_T *ar) { if (ar->arWowState!= WLAN_WOW_STATE_NONE) { A_UINT16 fg_start_period = (ar->scParams.fg_start_period==0) ? 1 : ar->scParams.fg_start_period; A_UINT16 bg_period = (ar->scParams.bg_period==0) ? 60 : ar->scParams.bg_period; WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = {TRUE, FALSE}; ar->arWowState = WLAN_WOW_STATE_NONE; #ifdef CONFIG_HAS_WAKELOCK wake_lock_timeout(&ar6k_wow_wake_lock, 3*HZ); #endif if (wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode)!=A_OK) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup restore host awake\n")); } #if WOW_SET_SCAN_PARAMS wmi_scanparams_cmd(ar->arWmi, fg_start_period, ar->scParams.fg_end_period, bg_period, ar->scParams.minact_chdwell_time, ar->scParams.maxact_chdwell_time, ar->scParams.pas_chdwell_time, ar->scParams.shortScanRatio, ar->scParams.scanCtrlFlags, ar->scParams.max_dfsch_act_time, ar->scParams.maxact_scan_per_ssid); #else (void)fg_start_period; (void)bg_period; #endif #if WOW_ENABLE_MAX_INTERVAL /* we don't do it if the power consumption is already good enough. */ if (wmi_listeninterval_cmd(ar->arWmi, ar->arListenIntervalT, ar->arListenIntervalB) == A_OK) { } #endif ar6k_send_asleep_event_to_app(ar, FALSE); AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Resume WoW successfully\n")); } else { AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("WoW does not invoked. skip resume")); } ar->arWlanPowerState = WLAN_POWER_STATE_ON; }
static void ar6000_wow_suspend(AR_SOFTC_T *ar) { #define WOW_LIST_ID 1 if (ar->arNetworkType != AP_NETWORK) { /* Setup WoW for unicast & Arp request for our own IP disable background scan. Set listen interval into 1000 TUs Enable keepliave for 110 seconds */ struct in_ifaddr **ifap = NULL; struct in_ifaddr *ifa = NULL; struct in_device *in_dev; A_UINT8 macMask[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; A_STATUS status; WMI_ADD_WOW_PATTERN_CMD addWowCmd = { .filter = { 0 } }; WMI_DEL_WOW_PATTERN_CMD delWowCmd; WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = {FALSE, TRUE}; WMI_SET_WOW_MODE_CMD wowMode = { .enable_wow = TRUE, .hostReqDelay = 500 };/*500 ms delay*/ if (ar->arWowState!= WLAN_WOW_STATE_NONE) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("System already go into wow mode!\n")); return; } ar6000_TxDataCleanup(ar); /* IMPORTANT, otherwise there will be 11mA after listen interval as 1000*/ #if WOW_ENABLE_MAX_INTERVAL /* we don't do it if the power consumption is already good enough. */ if (wmi_listeninterval_cmd(ar->arWmi, A_MAX_WOW_LISTEN_INTERVAL, 0) == A_OK) { } #endif #if WOW_SET_SCAN_PARAMS status = wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, 0xFFFF, 0, 0, 0, 0, 0, 0, 0); #endif /* clear up our WoW pattern first */ delWowCmd.filter_list_id = WOW_LIST_ID; delWowCmd.filter_id = 0; wmi_del_wow_pattern_cmd(ar->arWmi, &delWowCmd); /* setup unicast packet pattern for WoW */ if (ar->arNetDev->dev_addr[1]) { addWowCmd.filter_list_id = WOW_LIST_ID; addWowCmd.filter_size = 6; /* MAC address */ addWowCmd.filter_offset = 0; status = wmi_add_wow_pattern_cmd(ar->arWmi, &addWowCmd, ar->arNetDev->dev_addr, macMask, addWowCmd.filter_size); if (status != A_OK) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to add WoW pattern\n")); } } /* setup ARP request for our own IP */ if ((in_dev = __in_dev_get_rtnl(ar->arNetDev)) != NULL) { for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; ifap = &ifa->ifa_next) { if (!strcmp(ar->arNetDev->name, ifa->ifa_label)) { break; /* found */ } } } if (ifa && ifa->ifa_local) { WMI_SET_IP_CMD ipCmd; memset(&ipCmd, 0, sizeof(ipCmd)); ipCmd.ips[0] = ifa->ifa_local; status = wmi_set_ip_cmd(ar->arWmi, &ipCmd); if (status != A_OK) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup IP for ARP agent\n")); } } #ifndef ATH6K_CONFIG_OTA_MODE wmi_powermode_cmd(ar->arWmi, REC_POWER); #endif status = wmi_set_wow_mode_cmd(ar->arWmi, &wowMode); if (status != A_OK) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to enable wow mode\n")); } ar6k_send_asleep_event_to_app(ar, TRUE); status = wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode); if (status != A_OK) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to set host asleep\n")); } ar->arWowState = WLAN_WOW_STATE_SUSPENDING; if (ar->arTxPending[ar->arControlEp]) { A_UINT32 timeleft = wait_event_interruptible_timeout(arEvent, ar->arTxPending[ar->arControlEp] == 0, wmitimeout * HZ); if (!timeleft || signal_pending(current)) { /* what can I do? wow resume at once */ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup WoW. Pending wmi control data %d\n", ar->arTxPending[ar->arControlEp])); } } status = hifWaitForPendingRecv(ar->arHifDevice); ar->arWowState = WLAN_WOW_STATE_SUSPENDED; ar->arWlanPowerState = WLAN_POWER_STATE_WOW; } else { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Not allowed to go to WOW at this moment.\n")); } }
void CAR6KMini::WMIConnectIndication( IN USHORT Channel, IN PBYTE PeerBSSID, IN USHORT listenInterval, IN USHORT beaconInterval, NETWORK_TYPE networkType, IN BYTE assocReqLen, IN BYTE assocRespLen, IN PBYTE assocInfo, IN BYTE beaconIeLen) { BYTE len = 0; int i = 0; A_STATUS wmiStatus; bss_t * bss; NDIS_DEBUG_PRINTF(1,"WMIConnectIndication Enter , %02x:%02x:%02x:%02x:%02x:%02x \r\n", PeerBSSID[0],PeerBSSID[1],PeerBSSID[2],PeerBSSID[3],PeerBSSID[4],PeerBSSID[5]); /* Set the Listen interval to appropriate value (100/1000 TUs) depending * on the power mode setting. For REC Mode we always indicate 1000TUs to the * AP in the conn. req. but reset it appropriately here upon conn Ind. */ if( m_80211_PowerMode == Ndis802_11PowerModeFast_PSP ) { wmiStatus = wmi_listeninterval_cmd((struct wmi_t *)m_pWMI, m_ListenInterval, 0); if (wmiStatus != A_OK) { NDIS_DEBUG_PRINTF(DBG_ERR_LOG,"AR6K: ERROR - wmi_listeninterval_cmd failed = %u \r\n", wmiStatus); } } memcpy(m_PeerBSSID, PeerBSSID, ETHERNET_MAC_ADDRESS_LENGTH); m_ConnectedChannel = Channel; m_Connected = true; m_ConnectInProgress = false; m_AssocReqLen = assocReqLen; m_AssocRespLen = assocRespLen; m_BeaconIeLen = beaconIeLen; if (m_pAssocInfo != NULL) { A_FREE(m_pAssocInfo); } m_pAssocInfo = (PBYTE)malloc(m_AssocReqLen + m_AssocRespLen + m_BeaconIeLen); if(m_pAssocInfo == NULL ) { NDIS_DEBUG_PRINTF(DBG_ERR, " %s() -> malloc faile!! size = %d \r\n",__FUNCTION__, m_AssocReqLen + m_AssocRespLen + m_BeaconIeLen); return; } else { memcpy(m_pAssocInfo, assocInfo, m_AssocReqLen + m_AssocRespLen + m_BeaconIeLen); } // Send Command to Enable or disable Background Scan if (m_Config.bkScanEnable) { m_WMIBssFilter = ALL_BUT_BSS_FILTER; } else { m_WMIBssFilter = NONE_BSS_FILTER; } wmi_bssfilter_cmd((struct wmi_t *)m_pWMI, m_WMIBssFilter,0); //Add the key here for WEP encryption with open Auth or Autoswitch. // For Shared Auth, the keys are plumbed before the connect cmd is issued and // for WPA/WPA2, the keys are plumbed when the AddKey OID comes. if (m_AuthenticationMode == Ndis802_11AuthModeOpen || m_AuthenticationMode == Ndis802_11AuthModeAutoSwitch ) { if (m_EncryptionStatus == Ndis802_11WEPEnabled) { NDIS_DEBUG_PRINTF(DBG_TRACE, "WEP encryption \r\n"); for (i=0;i<4;i++) { if (m_cbKey[i] != 0) { NDIS_DEBUG_PRINTF(DBG_TRACE, "AR6K: adding WEP keys @ index %d \r\n", i); wmiStatus = wmi_addKey_cmd((wmi_t *)m_pWMI, (A_UINT8)m_KeyIndex[i], WEP_CRYPT, m_KeyUsage[i], (A_UINT8)m_cbKey[i], NULL, m_Key[i], KEY_OP_INIT_VAL,NULL,NO_SYNC_WMIFLAG); if (wmiStatus != A_OK) { NDIS_DEBUG_PRINTF(DBG_TRACE, "AR6K: ERROR - wmi_addKey_cmd failed = %u \r\n", wmiStatus); } } } } } // Indicate MEDIA_CONNECT to Ndis NdisMIndicateStatus(m_MiniportAdapterHandle, NDIS_STATUS_MEDIA_CONNECT, 0, 0); NdisMIndicateStatusComplete(m_MiniportAdapterHandle); bss=wmi_find_node((wmi_t *)m_pWMI,m_PeerBSSID); if (bss != NULL) { m_beaconInterval = bss->ni_cie.ie_beaconInt; } NDIS_DEBUG_PRINTF(DBG_TRACE,"%s() - Exit !! \r\n",__FUNCTION__); return; }