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 */ }
extern "C" void ar6k_rx(void *Context, HTC_PACKET *pPacket) { CAR6KMini *Adapter = (CAR6KMini *)Context; struct ndis_mini_buf_t * skb = (struct ndis_mini_buf_t *)pPacket->pPktContext; A_STATUS status = pPacket->Status; HTC_ENDPOINT_ID ept = pPacket->Endpoint; NDIS_DEBUG_PRINTF(0, " %s() + Enter \r\n",__FUNCTION__); A_ASSERT((status != A_OK) || (pPacket->pBuffer == (A_NETBUF_DATA(skb) + HTC_HEADER_LEN))); Adapter->m_RxBuffers[ept]--; if (A_SUCCESS(status)) { Adapter->Lock(); A_NETBUF_PUT(skb, pPacket->ActualLength + HTC_HEADER_LEN); A_NETBUF_PULL(skb, HTC_HEADER_LEN); Adapter->Unlock(); } if (status != A_OK) { A_NETBUF_FREE(skb); } else if (Adapter->m_WMIEnabled == TRUE) { if (ept == Adapter->m_ControlEp) { /* * this is a wmi control msg */ //wmi_control_rx((wmi_t *)ar->arWmi, skb, ar->arPhyCapability); /* Bug 82893 */ Adapter->ReceiveWMIControlPacket(pPacket); } else { // WMI Data packet (e.g. IP data packet) Adapter->ReceiveWMIDataPacket(pPacket); } } if (status != A_ECANCELED) { /* * HTC provides A_ECANCELED status when it doesn't want to be refilled * (probably due to a shutdown) */ Adapter->AR6KRxRefill(ept); } NDIS_DEBUG_PRINTF(0, "%s() -Exit \r\n", __FUNCTION__); }
/* Custom_DeliverFrameToNetworkStack - Called by API_RxComplete to * deliver a data frame to the network stack. This code will perform * platform specific operations. * void *pCxt - the driver context. * void *pReq - the packet. *****************************************************************************/ void Custom_DeliverFrameToNetworkStack(void *pCxt, void *pReq) { A_NETBUF *a_netbuf_ptr = (A_NETBUF *)pReq; QCA_CONTEXT_STRUCT_PTR qca_ptr = (QCA_CONTEXT_STRUCT_PTR)GET_DRIVER_CXT(pCxt)->pUpperCxt[0]; QCA_ECB_STRUCT_PTR RxECB; uint32_t len; A_DRIVER_CONTEXT *pDCxt = GET_DRIVER_COMMON(pCxt); ATH_PROMISCUOUS_CB prom_cb = (ATH_PROMISCUOUS_CB)(GET_DRIVER_CXT(pCxt)->promiscuous_cb); if (a_netbuf_ptr) { len = A_NETBUF_LEN(pReq); _DCACHE_INVALIDATE_MBYTES(A_NETBUF_DATA(pReq), len); if (pDCxt->promiscuous_mode) { if (prom_cb) { /* send frame to callback function rather than an QCA_receiver */ a_netbuf_ptr->native.FRAG[0].LENGTH = len; a_netbuf_ptr->native.FRAG[0].FRAGMENT = A_NETBUF_DATA(pReq); prom_cb((void *)&(a_netbuf_ptr->native)); } else { A_NETBUF_FREE(pReq); } } else if ((RxECB = QCA_find_receiver(qca_ptr, (QCA_HEADER_PTR)A_NETBUF_DATA(pReq), &len)) != NULL) { // Call the receiver's service function to pass the PCB to the receiver a_netbuf_ptr->native.FRAG[0].LENGTH = len; a_netbuf_ptr->native.FRAG[0].FRAGMENT = A_NETBUF_DATA(pReq); RxECB->SERVICE((PCB_PTR) & (a_netbuf_ptr->native), RxECB->PRIVATE); } else { /* failed to find a receiver for this data packet. */ A_NETBUF_FREE(pReq); } } }
static void RefillRecvBuffers(struct ar6k_hci_bridge_info *pHcidevInfo, HCI_TRANSPORT_PACKET_TYPE Type, int NumBuffers) { int length, i; void *osBuf = NULL; struct htc_packet_queue queue; struct htc_packet *pPacket; INIT_HTC_PACKET_QUEUE(&queue); if (Type == HCI_ACL_TYPE) { if (pHcidevInfo->HciNormalMode) { length = HCI_MAX_FRAME_SIZE; } else { length = MAX_ACL_RECV_LENGTH; } } else { length = MAX_EVT_RECV_LENGTH; } /* add on transport head and tail room */ length += pHcidevInfo->HCIProps.HeadRoom + pHcidevInfo->HCIProps.TailRoom; /* round up to the required I/O padding */ length = BLOCK_ROUND_UP_PWR2(length,pHcidevInfo->HCIProps.IOBlockPad); for (i = 0; i < NumBuffers; i++) { if (pHcidevInfo->HciNormalMode) { osBuf = bt_alloc_buffer(pHcidevInfo,length); } else { osBuf = A_NETBUF_ALLOC(length); } if (NULL == osBuf) { break; } pPacket = AllocHTCStruct(pHcidevInfo); if (NULL == pPacket) { FreeBtOsBuf(pHcidevInfo,osBuf); AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to alloc HTC struct \n")); break; } SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),length,Type); /* add to queue */ HTC_PACKET_ENQUEUE(&queue,pPacket); } if (i > 0) { HCI_TransportAddReceivePkts(pHcidevInfo->pHCIDev, &queue); } }
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 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); } } }
A_STATUS hci_test_send(AR_SOFTC_T *ar, struct sk_buff *skb) #endif { int status = A_OK; int length; EPPING_HEADER *pHeader; HTC_PACKET *pPacket; HTC_TX_TAG htc_tag = AR6K_DATA_PKT_TAG; #ifdef EXPORT_HCI_BRIDGE_INTERFACE AR6K_HCI_BRIDGE_INFO *pHcidevInfo = g_pHcidevInfo; #else AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)ar->hcidev_info; #endif do { if (NULL == pHcidevInfo) { status = A_ERROR; break; } if (NULL == pHcidevInfo->pHCIDev) { status = A_ERROR; break; } if (pHcidevInfo->HciNormalMode) { /* this interface cannot run when normal WMI is running */ status = A_ERROR; break; } pHeader = (EPPING_HEADER *)A_NETBUF_DATA(skb); if (!IS_EPPING_PACKET(pHeader)) { status = A_EINVAL; break; } if (IS_EPING_PACKET_NO_DROP(pHeader)) { htc_tag = AR6K_CONTROL_PKT_TAG; } length = sizeof(EPPING_HEADER) + pHeader->DataLength; pPacket = AllocHTCStruct(pHcidevInfo); if (NULL == pPacket) { status = A_NO_MEMORY; break; } SET_HTC_PACKET_INFO_TX(pPacket, skb, A_NETBUF_DATA(skb), length, HCI_ACL_TYPE, /* send every thing out as ACL */ htc_tag); HCI_TransportSendPkt(pHcidevInfo->pHCIDev,pPacket,FALSE); pPacket = NULL; } while (FALSE); return status; }