📄 rtusb_data.c
字号:
{ pAd->DeQueueRunning[BulkOutPipeId] = TRUE; NdisReleaseSpinLock(&pAd->DeQueueLock[BulkOutPipeId], IrqFlags); } QueIdx = BulkOutPipeId; if (pAd->TxRingTotalNumber[BulkOutPipeId]) DBGPRINT(RT_DEBUG_INFO,"--RTMPDeQueuePacket %d TxRingTotalNumber= %d !!--\n", BulkOutPipeId, (INT)pAd->TxRingTotalNumber[BulkOutPipeId]); // Make sure SendTxWait queue resource won't be used by other threads NdisAcquireSpinLock(&pAd->SendTxWaitQueueLock[BulkOutPipeId], IrqFlags); // Select Queue pQueue = &pAd->SendTxWaitQueue[BulkOutPipeId]; // Check queue before dequeue while ((pQueue->Head != NULL) && (Count < MAX_TX_PROCESS)) { // Reset is in progress, stop immediately if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) { DBGPRINT(RT_DEBUG_ERROR,"--RTMPDeQueuePacket %d reset-in-progress !!--\n", BulkOutPipeId); break; } // Dequeue the first entry from head of queue list pSkb = (struct sk_buff*)RemoveHeadQueue(pQueue); // RTS or CTS-to-self for B/G protection mode has been set already. // There is no need to re-do it here. // Total fragment required = number of fragment + RST if required FragmentRequired = RTMP_GET_PACKET_FRAGMENTS(pSkb) + RTMP_GET_PACKET_RTS(pSkb); if ((RTUSBFreeDescriptorRequest(pAd, TX_RING, BulkOutPipeId, FragmentRequired) == NDIS_STATUS_SUCCESS)) { // Avaliable ring descriptors are enough for this frame // Call hard transmit // Nitro mode / Normal mode selection NdisReleaseSpinLock(&pAd->SendTxWaitQueueLock[BulkOutPipeId], IrqFlags); Status = RTUSBHardTransmit(pAd, pSkb, FragmentRequired, QueIdx); // Acquire the resource again, snice we may need to process it in this while-loop. NdisAcquireSpinLock(&pAd->SendTxWaitQueueLock[BulkOutPipeId], IrqFlags); if (Status == NDIS_STATUS_FAILURE) { // Packet failed due to various Ndis Packet error RTUSBFreeSkbBuffer(pSkb); break; } else if (Status == NDIS_STATUS_RESOURCES) { // Not enough free tx ring, it might happen due to free descriptor inquery might be not correct // It also might change to NDIS_STATUS_FAILURE to simply drop the frame // Put the frame back into head of queue InsertHeadQueue(pQueue, pSkb); break; } Count++; } else { DBGPRINT(RT_DEBUG_INFO,"--RTMPDeQueuePacket %d queue full !! TxRingTotalNumber= %d !! FragmentRequired=%d !!\n", BulkOutPipeId, (INT)pAd->TxRingTotalNumber[BulkOutPipeId], FragmentRequired); InsertHeadQueue(pQueue, pSkb); pAd->PrivateInfo.TxRingFullCnt++; break; } } // Release TxSwQueue0 resources NdisReleaseSpinLock(&pAd->SendTxWaitQueueLock[BulkOutPipeId], IrqFlags);#ifdef BLOCK_NET_IF if ((pAd->blockQueueTab[QueIdx].SwTxQueueBlockFlag == TRUE) && (pAd->TxSwQueue[QueIdx].Number < 1)) { releaseNetIf(&pAd->blockQueueTab[QueIdx]); }#endif // BLOCK_NET_IF // NdisAcquireSpinLock(&pAd->DeQueueLock[BulkOutPipeId], IrqFlags); pAd->DeQueueRunning[BulkOutPipeId] = FALSE; NdisReleaseSpinLock(&pAd->DeQueueLock[BulkOutPipeId], IrqFlags); }/* ======================================================================== Description: This is the completion routine for the USB_RxPacket which submits a URB to USBD for a transmission. ========================================================================*/VOID RTUSBRxPacket( IN unsigned long data){ purbb_t pUrb = (purbb_t)data; PRTMP_ADAPTER pAd; PRX_CONTEXT pRxContext; PRXD_STRUC pRxD;#ifdef BIG_ENDIAN PRXD_STRUC pDestRxD; RXD_STRUC RxD;#endif PHEADER_802_11 pHeader; PUCHAR pData; PUCHAR pDA, pSA; NDIS_STATUS Status; USHORT DataSize, Msdu2Size; UCHAR Header802_3[14]; PCIPHER_KEY pWpaKey;// struct sk_buff *pSkb; BOOLEAN EAPOLFrame; struct net_device *net_dev; DBGPRINT_RAW(RT_DEBUG_INFO, "--->RTUSBRxPacket\n"); pRxContext = (PRX_CONTEXT)pUrb->context; pAd = pRxContext->pAd; net_dev = pAd->net_dev; if( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) ) return; do { DBGPRINT_RAW(RT_DEBUG_INFO, "BulkIn actual length(%d)\n", pRxContext->pUrb->actual_length); if (pRxContext->pUrb->actual_length >= sizeof(RXD_STRUC)+ LENGTH_802_11) { pData = pRxContext->TransferBuffer;#ifndef BIG_ENDIAN pRxD = (PRXD_STRUC) pData;#else pDestRxD = (PRXD_STRUC) pData; RxD = *pDestRxD; pRxD = &RxD; RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD);#endif // Cast to 802.11 header for flags checking pHeader = (PHEADER_802_11) (pData + sizeof(RXD_STRUC) ); #ifdef BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)pHeader, DIR_READ, FALSE);#endif if (pRxD->DataByteCnt < 4) Status = NDIS_STATUS_FAILURE; else { // Increase Total receive byte counter after real data received no mater any error or not pAd->RalinkCounters.ReceivedByteCount += (pRxD->DataByteCnt - 4); pAd->RalinkCounters.RxCount ++; // Check for all RxD errors Status = RTMPCheckRxDescriptor(pAd, pHeader, pRxD); } if (Status == NDIS_STATUS_SUCCESS) { // Apply packet filtering rule based on microsoft requirements. Status = RTMPApplyPacketFilter(pAd, pRxD, pHeader); } // Add receive counters if (Status == NDIS_STATUS_SUCCESS) { // Increase 802.11 counters & general receive counters INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount); } else { // Increase general counters pAd->Counters.RxErrors++; } #ifdef RALINK_ATE if((!pRxD->U2M) && pAd->ate.Mode != ATE_STASTART) { CHAR RealRssi; RealRssi = ConvertToRssi(pAd, (UCHAR)pRxD->PlcpRssi, RSSI_NO_1); pAd->PortCfg.LastRssi = RealRssi + pAd->BbpRssiToDbmDelta; pAd->PortCfg.AvgRssiX8 = (pAd->PortCfg.AvgRssiX8 - pAd->PortCfg.AvgRssi) + pAd->PortCfg.LastRssi; pAd->PortCfg.AvgRssi = pAd->PortCfg.AvgRssiX8 >> 3;// for smart antenna// if ((pAd->RfIcType == RFIC_5325) || (pAd->RfIcType == RFIC_2529))// {// pAd->PortCfg.LastRssi2 = ConvertToRssi(pAd, (UCHAR)pRxD->PlcpSignal, RSSI_NO_2) + pAd->BbpRssiToDbmDelta;// } }#endif // RALINK_ATE // Check for retry bit, if this bit is on, search the cache with SA & sequence // as index, if matched, discard this frame, otherwise, update cache // This check only apply to unicast data & management frames if ((pRxD->U2M) && (Status == NDIS_STATUS_SUCCESS) && (pHeader->FC.Type != BTYPE_CNTL)) { if (pHeader->FC.Retry) { if (RTMPSearchTupleCache(pAd, pHeader) == TRUE) { // Found retry frame in tuple cache, Discard this frame / fragment // Increase 802.11 counters INC_COUNTER64(pAd->WlanCounters.FrameDuplicateCount); DBGPRINT_RAW(RT_DEBUG_INFO, "duplicate frame %d\n", pHeader->Sequence); Status = NDIS_STATUS_FAILURE; } else { RTMPUpdateTupleCache(pAd, pHeader); } } else // Update Tuple Cache { RTMPUpdateTupleCache(pAd, pHeader); } } if ((pRxD->U2M) || ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->PortCfg.Bssid, &pHeader->Addr2)))) { if ((pAd->Antenna.field.NumOfAntenna == 2) && (pAd->Antenna.field.TxDefaultAntenna == 0) && (pAd->Antenna.field.RxDefaultAntenna == 0)) { COLLECT_RX_ANTENNA_AVERAGE_RSSI(pAd, ConvertToRssi(pAd, (UCHAR)pRxD->PlcpRssi, RSSI_NO_1), 0); //Note: RSSI2 not used on RT73 pAd->PortCfg.NumOfAvgRssiSample ++; } } // // Do RxD release operation for all failure frames // if (Status == NDIS_STATUS_SUCCESS) { do { if (VIRTUAL_IF_NUM(pAd)==0) break; // pData : Pointer skip the RxD Descriptior and the first 24 bytes, 802.11 HEADER pData += LENGTH_802_11 + sizeof(RXD_STRUC); DataSize = (USHORT) pRxD->DataByteCnt - LENGTH_802_11; // // CASE I. receive a DATA frame // if (pHeader->FC.Type == BTYPE_DATA) { // before LINK UP, all DATA frames are rejected if ( !OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) ) { DBGPRINT(RT_DEBUG_INFO,"RxDone- drop DATA frame before LINK UP(len=%d)\n",pRxD->DataByteCnt); break; } pAd->BulkInDataOneSecCount++; // remove the 2 extra QOS CNTL bytes if (pHeader->FC.SubType & 0x08) { pData += 2; DataSize -= 2; } // remove the 2 extra AGGREGATION bytes Msdu2Size = 0; if (pHeader->FC.Order) { Msdu2Size = *pData + (*(pData+1) << 8); if ((Msdu2Size <= 1536) && (Msdu2Size < DataSize)) { pData += 2; DataSize -= 2; } else Msdu2Size = 0; } // Drop not my BSS frame // // Not drop EAPOL frame, since this have happen on the first time that we link up // And need some more time to set BSSID to asic // So pRxD->MyBss may be 0 // if (RTMPEqualMemory(EAPOL, pData + 6, 2)) EAPOLFrame = TRUE; else EAPOLFrame = FALSE; if ((pRxD->MyBss == 0) && (EAPOLFrame != TRUE)) break; // give up this frame // Drop NULL (+CF-POLL) (+CF-ACK) data frame if ((pHeader->FC.SubType & 0x04) == 0x04) { DBGPRINT(RT_DEBUG_TRACE,"RxDone- drop NULL frame(subtype=%d)\n",pHeader->FC.SubType); break; } // prepare 802.3 header: DA=addr1; SA=addr3 in INFRA mode, DA=addr2 in ADHOC mode pDA = pHeader->Addr1; if (INFRA_ON(pAd)) pSA = pHeader->Addr3; else pSA = pHeader->Addr2; if (pHeader->FC.Wep) // frame received in encrypted format { if (pRxD->CipherAlg == CIPHER_NONE) // unsupported cipher suite { break; // give up this frame } else if (pAd->SharedKey[pRxD->KeyIndex].KeyLen == 0) { break; // give up this frame since the keylen is invalid. } } else { // frame received in clear text // encryption in-use but receive a non-EAPOL clear text frame, drop it if (((pAd->PortCfg.WepStatus == Ndis802_11Encryption1Enabled) || (pAd->PortCfg.WepStatus == Ndis802_11Encryption2Enabled) || (pAd->PortCfg.WepStatus == Ndis802_11Encryption3Enabled)) && (pAd->PortCfg.PrivacyFilter == Ndis802_11PrivFilter8021xWEP) && (!NdisEqualMemory(EAPOL_LLC_SNAP, pData, LENGTH_802_1_H))) { break; // give up this frame } } // // Case I.1 Process Broadcast & Multicast data frame // if (pRxD->Bcast || pRxD->Mcast) { PUCHAR pRemovedLLCSNAP; INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount); // Drop Mcast/Bcast frame with fragment bit on if (pHeader->FC.MoreFrag) { break; // give up this frame } // Filter out Bcast frame which AP relayed for us if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress)) { break; // give up this frame } // build 802.3 header and decide if remove the 8-byte LLC/SNAP encapsulation CONVERT_TO_802_3(Header802_3, pDA, pSA, pData, DataSize, pRemovedLLCSNAP); REPORT_ETHERNET_FRAME_TO_LLC(pAd,Header802_3, pData, DataSize, net_dev); DBGPRINT(RT_DEBUG_TRACE, "!!! report BCAST DATA to LLC (len=%d) !!!\n", DataSize); } // // Case I.2 Process unicast-to-me DATA frame // else if (pRxD->U2M) { RECORD_LATEST_RX_DATA_RATE(pAd, pRxD);//#ifdef RALINK_WPA_SUPPLICANT_SUPPORT if (pAd->PortCfg.WPA_Supplicant == TRUE) { // All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon) // TBD : process fragmented EAPol frames //2007/12/21:Carella add to fix fragmentation bugs in 802.1x(start) if (pHeader->Frag == 0) { // First or Only fragment if (pHeader->FC.MoreFrag == FALSE) { // One & The only fragment if(NdisEqualMemory(EAPOL_LLC_SNAP, pData, LENGTH_802_1_H)) { PUCHAR pRemovedLLCSNAP; int success = 0; // In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable if ( pAd->PortCfg.IEEE8021X == TRUE && (EAP_CODE_SUCCESS == RTMPCheckWPAframeForEapCode(pAd, pData, DataSize, LENGTH_802_1_H))) { DBGPRINT_RAW(RT_DEBUG_TRACE, "Receive EAP-SUCCESS Packet\n"); pAd->PortCfg.PortSecured = WPA_802_1X_PORT_SECURED; success = 1; } // build 802.3 header and decide if remove the 8-byte LLC/SNAP encapsulation CONVERT_TO_802_3(Header802_3, pDA, pSA, pData, DataSize, pRemovedLLCSNAP); REPORT_ETHERNET_FRAME_TO_LLC(pAd, Header802_3, pData, DataSize, net_dev); DBGPRINT_RAW(RT_DEBUG_TRACE, "!!! report EAPoL DATA to LLC (len=%d) !!!\n", DataSize); if(success) { // For static wep mode, need to set wep key to Asic again if(pAd->PortCfg.IEEE8021x_required_keys == 0) { int idx; idx = pAd->PortCfg.DefaultKeyId; DBGPRINT_RAW(RT_DEBUG_TRACE, "Set WEP key to Asic again =>\n"); if(pAd->PortCfg.DesireSharedKey[idx].KeyLen != 0) { pAd->SharedKey[idx].KeyLen = pAd->PortCfg.DesireSharedKey[idx].KeyLen; NdisMoveMemory(pAd->SharedKey[idx].Key, pAd->PortCfg.DesireSharedKey[idx].Key, pAd->SharedKey[idx].KeyLen); pAd->SharedKey[idx].CipherAlg = pAd->PortCfg.DesireSharedKey[idx].CipherAlg; AsicAddSharedKeyEntry(pAd, 0, (UCHAR)idx, pAd->SharedKey[idx].CipherAlg, pAd->SharedKey[idx].Key, NULL, NULL); } } } break; //After reporting to LLC, must break } }//End of One & The only fragment else { // First fragment - record the 802.3 header and frame body if (NdisEqualMemory(EAPOL_LLC_SNAP, pData, LENGTH_802_1_H)) { NdisMoveMemory(&pAd->FragFrame.Buffer[LENGTH_802_3], pData, DataSize); NdisMoveMemory(pAd->FragFrame.Header802_3, Header802_3, LENGTH_802_3); pAd->FragFrame.RxSize = DataSize; pAd->FragFrame.Sequence = pHeader->Sequence; pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0 break; } } }//End of First or Only fragment else { // Middle & End of fragment burst fragments // No LLC-SNAP header in except the first fragment frame // Here only handle the EAPOL middle or final fragment if (RTMPEqualMemory(SNAP_802_1H, (PUCHAR)&pAd->FragFrame.Buffer[LENGTH_802_3], 6)) { if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||(pHeader->Frag != (pAd->FragFrame.LastFrag + 1))) { // Fragment is not the same sequence or out of fragment number order // Clear Fragment frame contents NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME)); break; // give up this frame
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -