static void prvInterruptSimulatorTask( void *pvParameters ) { static struct pcap_pkthdr *pxHeader; const uint8_t *pucPacketData; long lResult; xNetworkBufferDescriptor_t *pxNetworkBuffer; xIPStackEvent_t xRxEvent = { eEthernetRxEvent, NULL }; eFrameProcessingResult_t eResult; /* Just to kill the compiler warning. */ ( void ) pvParameters; for( ;; ) { /* Get the next packet. */ xSemaphoreTake( xPCAPMutex, portMAX_DELAY ); { lResult = pcap_next_ex( pxOpenedInterfaceHandle, &pxHeader, &pucPacketData ); } xSemaphoreGive( xPCAPMutex ); if( lResult == 1 ) { eResult = ipCONSIDER_FRAME_FOR_PROCESSING( pucPacketData ); if( eResult == eProcessBuffer ) { /* Will the data fit into the frame buffer? */ if( pxHeader->len <= ipTOTAL_ETHERNET_FRAME_SIZE ) { /* Obtain a buffer into which the data can be placed. This is only an interrupt simulator, not a real interrupt, so it is ok to call the task level function here. */ xSemaphoreTake( xPCAPMutex, portMAX_DELAY ); { pxNetworkBuffer = pxNetworkBufferGet( pxHeader->len, 0 ); } xSemaphoreGive( xPCAPMutex ); if( pxNetworkBuffer != NULL ) { memcpy( pxNetworkBuffer->pucEthernetBuffer, pucPacketData, pxHeader->len ); pxNetworkBuffer->xDataLength = ( size_t ) pxHeader->len; xRxEvent.pvData = ( void * ) pxNetworkBuffer; /* Data was received and stored. Send a message to the IP task to let it know. */ if( xQueueSendToBack( xNetworkEventQueue, &xRxEvent, ( portTickType ) 0 ) == pdFALSE ) { /* The buffer could not be sent to the stack so must be released again. This is only an interrupt simulator, not a real interrupt, so it is ok to use the task level function here. */ vNetworkBufferRelease( pxNetworkBuffer ); iptraceETHERNET_RX_EVENT_LOST(); } else { iptraceNETWORK_INTERFACE_RECEIVE(); } } else { iptraceETHERNET_RX_EVENT_LOST(); } } else { /* Log that a packet was dropped because it would have overflowed the buffer. */ } } } else { /* There is no real way of simulating an interrupt. Make sure other tasks can run. */ vTaskDelay( configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY ); } } }
static void prvInterruptSimulatorTask( void *pvParameters ) { struct pcap_pkthdr xHeader; static struct pcap_pkthdr *pxHeader; const uint8_t *pucPacketData; uint8_t ucRecvBuffer[ ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ]; NetworkBufferDescriptor_t *pxNetworkBuffer; IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL }; eFrameProcessingResult_t eResult; /* Remove compiler warnings about unused parameters. */ ( void ) pvParameters; for( ;; ) { /* Does the circular buffer used to pass data from the Win32 thread that handles WinPCAP Rx into the FreeRTOS simulator contain another packet? */ if( uxStreamBufferGetSize( xRecvBuffer ) > sizeof( xHeader ) ) { /* Get the next packet. */ uxStreamBufferGet( xRecvBuffer, 0, (uint8_t*)&xHeader, sizeof( xHeader ), pdFALSE ); uxStreamBufferGet( xRecvBuffer, 0, (uint8_t*)ucRecvBuffer, ( size_t ) xHeader.len, pdFALSE ); pucPacketData = ucRecvBuffer; pxHeader = &xHeader; iptraceNETWORK_INTERFACE_RECEIVE(); eResult = ipCONSIDER_FRAME_FOR_PROCESSING( pucPacketData ); if( eResult == eProcessBuffer ) { /* Will the data fit into the frame buffer? */ if( pxHeader->len <= ipTOTAL_ETHERNET_FRAME_SIZE ) { /* Obtain a buffer into which the data can be placed. This is only an interrupt simulator, not a real interrupt, so it is ok to call the task level function here, but note that some buffer implementations cannot be called from a real interrupt. */ pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( pxHeader->len, 0 ); if( pxNetworkBuffer != NULL ) { memcpy( pxNetworkBuffer->pucEthernetBuffer, pucPacketData, pxHeader->len ); pxNetworkBuffer->xDataLength = ( size_t ) pxHeader->len; #if( niDISRUPT_PACKETS == 1 ) { pxNetworkBuffer = vRxFaultInjection( pxNetworkBuffer, pucPacketData ); } #endif /* niDISRUPT_PACKETS */ if( pxNetworkBuffer != NULL ) { xRxEvent.pvData = ( void * ) pxNetworkBuffer; /* Data was received and stored. Send a message to the IP task to let it know. */ if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL ) { /* The buffer could not be sent to the stack so must be released again. This is only an interrupt simulator, not a real interrupt, so it is ok to use the task level function here, but note no all buffer implementations will allow this function to be executed from a real interrupt. */ vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); iptraceETHERNET_RX_EVENT_LOST(); } } else { /* The packet was already released or stored inside vRxFaultInjection(). Don't release it here. */ } } else { iptraceETHERNET_RX_EVENT_LOST(); } } else { /* Log that a packet was dropped because it would have overflowed the buffer, but there may be more buffers to process. */ } } } else { /* There is no real way of simulating an interrupt. Make sure other tasks can run. */ vTaskDelay( configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY ); } } }