void android_ar6k_check_wow_status(AR_SOFTC_T *ar, struct sk_buff *skb, A_BOOL isEvent) { #ifdef CONFIG_PM if (ar->arWowState!=WOW_STATE_NONE) { if (ar->arWowState==WOW_STATE_SUSPENDING) { AR_DEBUG_PRINTF(ATH_DEBUG_SUSPEND,("%s: Received IRQ while we are wow suspending!!!\n", __func__)); return; } /* Wow resume from irq interrupt */ AR_DEBUG_PRINTF(ATH_DEBUG_SUSPEND, ("%s: WoW resume from irq thread status %d\n", __func__, ar->arOsPowerCtrl)); ar6000_wow_resume(ar); ar->arOsPowerCtrl = WLAN_PWR_CTRL_UP; } else if (screen_is_off && skb && ar->arConnected) { A_BOOL needWake = FALSE; if (isEvent) { if (A_NETBUF_LEN(skb) >= sizeof(A_UINT16)) { A_UINT16 cmd = *(const A_UINT16 *)A_NETBUF_DATA(skb); switch (cmd) { case WMI_CONNECT_EVENTID: case WMI_DISCONNECT_EVENTID: needWake = TRUE; break; default: /* dont wake lock the system for other event */ break; } } } else if (A_NETBUF_LEN(skb) >= sizeof(ATH_MAC_HDR)) { ATH_MAC_HDR *datap = (ATH_MAC_HDR *)A_NETBUF_DATA(skb); if (!IEEE80211_IS_MULTICAST(datap->dstMac)) { switch (A_BE2CPU16(datap->typeOrLen)) { case 0x0800: /* IP */ case 0x888e: /* EAPOL */ case 0x88c7: /* RSN_PREAUTH */ case 0x88b4: /* WAPI */ needWake = TRUE; break; case 0x0806: /* ARP is not important to hold wake lock */ default: break; } } } if (needWake) { /* keep host wake up if there is any event and packate comming in*/ wake_lock_timeout(&ar6k_wow_wake_lock, 3*HZ); if (wowledon) { char buf[32]; int len = sprintf(buf, "on"); android_readwrite_file("/sys/power/state", NULL, buf, len); len = sprintf(buf, "%d", 127); android_readwrite_file("/sys/class/leds/lcd-backlight/brightness", NULL, buf,len); } } } #endif /* CONFIG_PM */ }
void android_ar6k_check_wow_status(AR_SOFTC_T *ar, struct sk_buff *skb, A_BOOL isEvent) { #ifdef CONFIG_HAS_WAKELOCK unsigned long wake_timeout = HZ; /* 1 second for normal window's ping test */ #endif AR_SOFTC_DEV_T *arPriv; A_UINT8 i; A_BOOL needWake = FALSE; for(i = 0; i < num_device; i++) { arPriv = ar->arDev[i]; if ( #ifdef CONFIG_HAS_EARLYSUSPEND screen_is_off && #endif skb && arPriv->arConnected) { if (isEvent) { if (A_NETBUF_LEN(skb) >= sizeof(A_UINT16)) { A_UINT16 cmd = *(const A_UINT16 *)A_NETBUF_DATA(skb); switch (cmd) { case WMI_CONNECT_EVENTID: #ifdef CONFIG_HAS_WAKELOCK wake_timeout = 3*HZ; #endif needWake = TRUE; break; default: /* dont wake lock the system for other event */ break; } } } else if (A_NETBUF_LEN(skb) >= sizeof(ATH_MAC_HDR)) { ATH_MAC_HDR *datap = (ATH_MAC_HDR *)A_NETBUF_DATA(skb); if (!IEEE80211_IS_MULTICAST(datap->dstMac)) { switch (A_BE2CPU16(datap->typeOrLen)) { case 0x0800: /* IP */ if (A_NETBUF_LEN(skb)>=24 && *((A_UCHAR*)A_NETBUF_DATA(skb)+23)==0x11) { A_UCHAR *udpPkt = (A_UCHAR*)A_NETBUF_DATA(skb)+14; A_UINT8 ihl = (*udpPkt & 0x0f) * sizeof(A_UINT32); const A_UCHAR ipsec_keepalive[] = { 0x11, 0x94, 0x11, 0x94, 0x00, 0x09, 0x00, 0x00, 0xff }; udpPkt += ihl; if (A_NETBUF_LEN(skb)>=14+ihl+sizeof(ipsec_keepalive) && !memcmp(udpPkt, ipsec_keepalive, sizeof(ipsec_keepalive)-3) && udpPkt[8]==0xff) { /* * RFC 3948 UDP Encapsulation of IPsec ESP Packets * Source and Destination port must be 4500 * Receivers MUST NOT depend upon the UDP checksum being zero * Sender must use 1 byte payload with 0xff * Receiver SHOULD ignore a received NAT-keepalive packet * * IPSec over UDP NAT keepalive packet. Just ignore */ break; } } case 0x888e: /* EAPOL */ case 0x88c7: /* RSN_PREAUTH */ case 0x88b4: /* WAPI */ needWake = TRUE; break; case 0x0806: /* ARP is not important to hold wake lock */ needWake = (arPriv->arNetworkType==AP_NETWORK); break; default: break; } } else if ( !IEEE80211_IS_BROADCAST(datap->dstMac) ) { if (A_NETBUF_LEN(skb)>=14+20 ) { /* check if it is mDNS packets */ A_UINT8 *dstIpAddr = (A_UINT8*)(A_NETBUF_DATA(skb)+14+20-4); struct net_device *ndev = arPriv->arNetDev; needWake = ((dstIpAddr[3] & 0xf8) == 0xf8) && (arPriv->arNetworkType==AP_NETWORK || (ndev->flags & IFF_ALLMULTI || ndev->flags & IFF_MULTICAST)); } }else if (arPriv->arNetworkType==AP_NETWORK) { switch (A_BE2CPU16(datap->typeOrLen)) { case 0x0800: /* IP */ if (A_NETBUF_LEN(skb)>=14+20+2) { A_UINT16 dstPort = *(A_UINT16*)(A_NETBUF_DATA(skb)+14+20); dstPort = A_BE2CPU16(dstPort); needWake = (dstPort == 0x43); /* dhcp request */ } break; case 0x0806: needWake = TRUE; default: break; } } } } } if (needWake) { #ifdef CONFIG_HAS_WAKELOCK /* keep host wake up if there is any event and packate comming in*/ wake_lock_timeout(&ar6k_wow_wake_lock, wake_timeout); #endif if (wowledon) { char buf[32]; int len = sprintf(buf, "on"); android_readwrite_file("/sys/power/state", NULL, buf, len); len = sprintf(buf, "%d", 127); android_readwrite_file("/sys/class/leds/lcd-backlight/brightness", NULL, buf,len); } } }
void CAR6KMini::ReceiveWMIDataPacket( HTC_EVENT_INFO *evInfo) // // This function processes data from an HTC_BUFFER_RECEIVED indication // not on the WMI_CONTROL_MBOX endpoint. // { ndis_mini_buf_t *pb = (ndis_mini_buf_t *)evInfo->cookie; NDIS_STATUS Status; NDIS_PACKET *pPacket; NDIS_BUFFER *pBuffer; PBYTE pData; ULONG cbData; BOOL doDix = FALSE; USHORT etherType; SNAP_HEADER *pSnapHdr; MAC_ADDRESS *pDestAddr,*tempAddr; BOOL mcForUs = FALSE; NDIS_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_RECV, "AR6K: +ReceiveWMIDataPacket"); if (evInfo->status != A_OK) { NDIS_DEBUG_PRINTF(ATH_LOG_ERR, "AR6K: ERROR - ReceiveWMIPacket Error in receiving : status = %x\n", evInfo->status); if (A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) { a_netbuf_free(pb); } goto done; } // evInfo->actualLength is the length of the pb->data including // 2 bytes: WMI_DATA_HEADER [optional - only if HTC header is 46 00] // 14 bytes: 802.3 MAC header // 8 bytes: SNAP header (with EthType as last 2 bytes) // N bytes: payload (e.g. IP packet) pData = evInfo->buffer; cbData = evInfo->actualLength; // Remove the WMI_DATA_HDR. if (cbData < sizeof(WMI_DATA_HDR)) { NDIS_DEBUG_PRINTF(ATH_LOG_ERR, "AR6K: ERROR - ReceiveWMIPacket missing WMI header (%u bytes)\n", evInfo->actualLength); if ( A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) { a_netbuf_free(pb); } goto done; } pData += sizeof(WMI_DATA_HDR); cbData -= sizeof(WMI_DATA_HDR); if (cbData < sizeof(ETHERNET_MAC_HEADER) + sizeof(SNAP_HEADER)) { NDIS_DEBUG_PRINTF(ATH_LOG_ERR, "AR6K: ERROR - ReceiveWMIPacket missing MAC + SNAP (%u bytes)\n", cbData); if ( A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) { a_netbuf_free(pb); } goto done; } #ifdef WMM Lock(); wmi_implicit_create_pstream((wmi_t *)m_pWMI, pb, DNLINK_TRAFFIC,1); Unlock(); #endif //WMM pDestAddr=(MAC_ADDRESS *)pData; /* Apply NDIS receive filter */ if (isGrp(pDestAddr)) { if (isBcast(pDestAddr)) { if (!(m_CurrentPacketFilter & NDIS_PACKET_TYPE_BROADCAST)) { if ( A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) { a_netbuf_free(pb); } goto done; } } else { isMcForUs(pDestAddr,&mcForUs); if (!(m_CurrentPacketFilter & (NDIS_PACKET_TYPE_MULTICAST | NDIS_PACKET_TYPE_ALL_MULTICAST)) || !(mcForUs)) { if ( A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) { a_netbuf_free(pb); } goto done; } } } else { tempAddr=(MAC_ADDRESS *) m_PermanentAddress; if ((A_MACADDR_COMP(pDestAddr,tempAddr) != 0) && !(m_CurrentPacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS)) { if ( A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) { a_netbuf_free(pb); } goto done; } } // Allocate an NDIS_PACKET from our packet pool. NdisAllocatePacket(&Status, &pPacket, m_RxPacketPool); if (NDIS_STATUS_SUCCESS != Status) { NDIS_DEBUG_PRINTF(ATH_LOG_ERR, "AR6K: ERROR - NdisAllocatePacket failed\n"); if ( A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) { a_netbuf_free(pb); } goto done; } // Check for ethernetType in SNAP header for NOVELL_IPX, APPLE_TALK_ARP etc // remove 802.3 length and SNAP header if it is not of these types pSnapHdr=(SNAP_HEADER *)(pData+sizeof(ETHERNET_MAC_HEADER)); etherType=A_BE2CPU16(pSnapHdr->Type); doDix=((A_MEMCMP(pSnapHdr,&bridgeTunnel, sizeof(CAP_CONST))) == 0); if((!doDix) && ((A_MEMCMP(pSnapHdr,&vrfc1042, sizeof(CAP_CONST))) == 0)) { doDix = ((etherType != APPLE_TALK_ARP) && (etherType != NOVELL_IPX)); } // Get rid of the 802.3 length and SNAP header by copying // the 802.3 DestMACAddr and SrcMACAddr forward so they // immediately precede the EthType at the end of the SNAP header. // That gives us a DIX packet. if (doDix) { memmove(pData + sizeof(SNAP_HEADER), pData, ETHERNET_MAC_ADDRESS_LENGTH * 2); pData += sizeof(SNAP_HEADER); cbData -= sizeof(SNAP_HEADER); } // Setup the fields of NDIS_BUFFER to point to our data. pBuffer = &pb->NdisBuffer; NdisInitializeBuffer(pBuffer, pData, cbData); // Chain the NDIS_BUFFER to the start of the NDIS_PACKET NdisChainBufferAtBack(pPacket, pBuffer); NDIS_SET_PACKET_HEADER_SIZE(pPacket, sizeof(ETHERNET_MAC_HEADER)); NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_SUCCESS); #ifdef NDIS_BUS_DRIVER NDIS_PACKET *PacketArray[1]; PacketArray[0]=pPacket; NdisMIndicateReceivePacket(m_MiniportAdapterHandle, PacketArray, 1); #else // Perform the indicate on the timer thread because tying up the // SDIO receive indication thread can result in a deadlock. PLIST_ENTRY pEntry = (PLIST_ENTRY)(pPacket->MiniportReserved); Lock(); InsertTailList(&m_RxPendingPacketList, pEntry); NdisSetEvent(&m_RxPendingEvent); Unlock(); #endif done: NDIS_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_RECV, "AR6K: -ReceiveWMIDataPacket"); }
void android_ar6k_check_wow_status(AR_SOFTC_T *ar, struct sk_buff *skb, A_BOOL isEvent) { AR_SOFTC_DEV_T *arPriv; A_UINT8 i; A_BOOL needWake = FALSE; for(i = 0; i < num_device; i++) { arPriv = ar->arDev[i]; if ( #ifdef CONFIG_HAS_EARLYSUSPEND screen_is_off && #endif skb && arPriv->arConnected) { if (isEvent) { if (A_NETBUF_LEN(skb) >= sizeof(A_UINT16)) { A_UINT16 cmd = *(const A_UINT16 *)A_NETBUF_DATA(skb); switch (cmd) { case WMI_CONNECT_EVENTID: case WMI_DISCONNECT_EVENTID: needWake = TRUE; break; default: /* dont wake lock the system for other event */ break; } } } else if (A_NETBUF_LEN(skb) >= sizeof(ATH_MAC_HDR)) { ATH_MAC_HDR *datap = (ATH_MAC_HDR *)A_NETBUF_DATA(skb); if (!IEEE80211_IS_MULTICAST(datap->dstMac)) { switch (A_BE2CPU16(datap->typeOrLen)) { case 0x0800: /* IP */ case 0x888e: /* EAPOL */ case 0x88c7: /* RSN_PREAUTH */ case 0x88b4: /* WAPI */ needWake = TRUE; break; case 0x0806: /* ARP is not important to hold wake lock */ needWake = (arPriv->arNetworkType==AP_NETWORK); break; default: break; } } else if ( !IEEE80211_IS_BROADCAST(datap->dstMac) ) { if (A_NETBUF_LEN(skb)>=14+20 ) { /* check if it is mDNS packets */ A_UINT8 *dstIpAddr = (A_UINT8*)(A_NETBUF_DATA(skb)+14+20-4); struct net_device *ndev = arPriv->arNetDev; needWake = ((dstIpAddr[3] & 0xf8) == 0xf8) && (arPriv->arNetworkType==AP_NETWORK || (ndev->flags & IFF_ALLMULTI || ndev->flags & IFF_MULTICAST)); } }else if (arPriv->arNetworkType==AP_NETWORK) { switch (A_BE2CPU16(datap->typeOrLen)) { case 0x0800: /* IP */ if (A_NETBUF_LEN(skb)>=14+20+2) { A_UINT16 dstPort = *(A_UINT16*)(A_NETBUF_DATA(skb)+14+20); dstPort = A_BE2CPU16(dstPort); needWake = (dstPort == 0x43); /* dhcp request */ } break; case 0x0806: needWake = TRUE; default: break; } } } } } if (needWake) { #ifdef CONFIG_HAS_WAKELOCK /* keep host wake up if there is any event and packate comming in*/ wake_lock_timeout(&ar6k_wow_wake_lock, 3*HZ); #endif if (wowledon) { char buf[32]; int len = sprintf(buf, "on"); android_readwrite_file("/sys/power/state", NULL, buf, len); len = sprintf(buf, "%d", 127); android_readwrite_file("/sys/class/leds/lcd-backlight/brightness", NULL, buf,len); } } }