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 */
}
Exemple #2
0
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__);
}
Exemple #3
0
/*  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);
        }
    }
}
Exemple #4
0
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;
}