]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Labs/Demo/FreeRTOS_IoT_Libraries/jobs/jobs_notify_next/WinPCap/arch.c
Add the Labs projects provided in the V10.2.1_191129 zip file.
[freertos] / FreeRTOS-Labs / Demo / FreeRTOS_IoT_Libraries / jobs / jobs_notify_next / WinPCap / arch.c
diff --git a/FreeRTOS-Labs/Demo/FreeRTOS_IoT_Libraries/jobs/jobs_notify_next/WinPCap/arch.c b/FreeRTOS-Labs/Demo/FreeRTOS_IoT_Libraries/jobs/jobs_notify_next/WinPCap/arch.c
new file mode 100644 (file)
index 0000000..02bf82b
--- /dev/null
@@ -0,0 +1,336 @@
+/*\r
+ * FreeRTOS Kernel V10.2.1\r
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://aws.amazon.com/freertos\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ */\r
+\r
+/* WinPCap includes. */\r
+#include "pcap.h"\r
+#include "remote-ext.h"\r
+\r
+/* uIP includes. */\r
+#include "net/uip.h"\r
+#include "net/uip_arp.h"\r
+#include "net/clock-arch.h"\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+\r
+/*\r
+ * Query the computer the simulation is being executed on to find the network\r
+ * interfaces it has installed.\r
+ */\r
+static pcap_if_t * prvPrintAvailableNetworkInterfaces( void );\r
+\r
+/*\r
+ * Open the network interface.  The number of the interface to be opened is set\r
+ * by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.\r
+ */\r
+static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces );\r
+\r
+/*\r
+ * Configure the capture filter to allow blocking reads, and to filter out\r
+ * packets that are not of interest to this demo.\r
+ */\r
+static void prvConfigureCaptureBehaviour( void );\r
+\r
+pcap_t *pxOpenedInterfaceHandle = NULL;\r
+LARGE_INTEGER freq, sys_start_time;\r
+\r
+#define archNUM_BUFFERS        5\r
+#define archNUM_BUFFER_POINTERS ( archNUM_BUFFERS - 1 )\r
+\r
+static void prvInterruptSimulator( void *pvParameters );\r
+\r
+static unsigned char ucEthernetBuffer[ archNUM_BUFFERS ][ UIP_CONF_BUFFER_SIZE ];\r
+static unsigned char *pucEthernetBufferPointers[ archNUM_BUFFER_POINTERS ];\r
+\r
+static long lLengthOfDataInBuffer[ archNUM_BUFFER_POINTERS ] = { 0 };\r
+static unsigned char ucNextBufferToFill = 0U, ucNextBufferToProcess = 0U;\r
+\r
+unsigned char *uip_buf = NULL;\r
+char cErrorBuffer[PCAP_ERRBUF_SIZE];\r
+\r
+void vNetifTx( void )\r
+{\r
+       pcap_sendpacket( pxOpenedInterfaceHandle, uip_buf, uip_len );\r
+       pcap_sendpacket( pxOpenedInterfaceHandle, uip_buf, uip_len );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+UBaseType_t uxNetifRx( void )\r
+{\r
+UBaseType_t xDataLen;\r
+unsigned char *pucTemp;\r
+\r
+       /* Check there is really data available. */\r
+       xDataLen = lLengthOfDataInBuffer[ ucNextBufferToProcess ];\r
+       if( xDataLen != 0L )\r
+       {\r
+\r
+               /* The buffer pointed to by uip_buf is going to change.  Remember which\r
+               buffer uip_buf is currently pointing to. */\r
+               pucTemp = uip_buf;\r
+\r
+               /* Point uip_buf at the next buffer that contains data. */\r
+               uip_buf = pucEthernetBufferPointers[ ucNextBufferToProcess ];\r
+\r
+               /* The buffer pointed to by \r
+               pucEthernetBufferPointeres[ ucNextBufferToProcess ] is now in use by\r
+               uip_buf, but the buffer uip_buf was pointing to on entry to this\r
+               function is free.  Set \r
+               pucEthernetBufferPointeres[ ucNextBufferToProcess ] to the free \r
+               buffer. */\r
+               pucEthernetBufferPointers[ ucNextBufferToProcess ] = pucTemp;\r
+               lLengthOfDataInBuffer[ ucNextBufferToProcess ] = 0L;\r
+\r
+               ucNextBufferToProcess++;\r
+               if( ucNextBufferToProcess >= archNUM_BUFFER_POINTERS )\r
+               {\r
+                       ucNextBufferToProcess = 0L;\r
+               }\r
+       }\r
+\r
+       return xDataLen;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetifInit( void )\r
+{\r
+BaseType_t x;\r
+pcap_if_t *pxAllNetworkInterfaces;\r
+\r
+       /* Allocate a free buffer to each buffer pointer. */\r
+       for( x = 0; x < sizeof( pucEthernetBufferPointers ) / sizeof( unsigned char * ); x++ )\r
+       {\r
+               pucEthernetBufferPointers[ x ] = &( ucEthernetBuffer[ x ][ 0 ] );\r
+       }\r
+\r
+       /* Start with uip_buf pointing to a buffer that is not referenced from the\r
+       pucEthernetBufferPointers[] array. */\r
+       uip_buf = &( ucEthernetBuffer[ archNUM_BUFFERS - 1 ][ 0 ] );\r
+\r
+       /* Query the computer the simulation is being executed on to find the \r
+       network interfaces it has installed. */\r
+       pxAllNetworkInterfaces = prvPrintAvailableNetworkInterfaces();\r
+       \r
+       /* Open the network interface.  The number of the interface to be opened is \r
+       set by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.\r
+       Calling this function will set the pxOpenedInterfaceHandle variable.  If,\r
+       after calling this function, pxOpenedInterfaceHandle is equal to NULL, then\r
+       the interface could not be opened. */\r
+       if( pxAllNetworkInterfaces != NULL )\r
+       {\r
+               prvOpenSelectedNetworkInterface( pxAllNetworkInterfaces );\r
+       }\r
+       \r
+\r
+       return x;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static pcap_if_t * prvPrintAvailableNetworkInterfaces( void )\r
+{    \r
+pcap_if_t * pxAllNetworkInterfaces = NULL, *xInterface;\r
+long lInterfaceNumber = 1;\r
+\r
+    if( pcap_findalldevs_ex( PCAP_SRC_IF_STRING, NULL, &pxAllNetworkInterfaces, cErrorBuffer ) == -1 )\r
+    {\r
+        printf( "\r\nCould not obtain a list of network interfaces\r\n%s\r\n", cErrorBuffer );\r
+        pxAllNetworkInterfaces = NULL;\r
+    }\r
+\r
+       if( pxAllNetworkInterfaces != NULL )\r
+       {\r
+               /* Print out the list of network interfaces.  The first in the list\r
+               is interface '1', not interface '0'. */\r
+               for( xInterface = pxAllNetworkInterfaces; xInterface != NULL; xInterface = xInterface->next )\r
+               {\r
+                       printf( "%d. %s", lInterfaceNumber, xInterface->name );\r
+                       \r
+                       if( xInterface->description != NULL )\r
+                       {\r
+                               printf( " (%s)\r\n", xInterface->description );\r
+                       }\r
+                       else\r
+                       {\r
+                               printf( " (No description available)\r\n") ;\r
+                       }\r
+                       \r
+                       lInterfaceNumber++;\r
+               }\r
+       }\r
+\r
+    if( lInterfaceNumber == 1 )\r
+    {\r
+               /* The interface number was never incremented, so the above for() loop\r
+               did not execute meaning no interfaces were found. */\r
+        printf( " \r\nNo network interfaces were found.\r\n" );\r
+        pxAllNetworkInterfaces = NULL;\r
+    }\r
+\r
+       printf( "\r\nThe interface that will be opened is set by configNETWORK_INTERFACE_TO_USE which should be defined in FreeRTOSConfig.h\r\n" );\r
+       printf( "Attempting to open interface number %d.\r\n", configNETWORK_INTERFACE_TO_USE );\r
+       \r
+    if( ( configNETWORK_INTERFACE_TO_USE < 1L ) || ( configNETWORK_INTERFACE_TO_USE > lInterfaceNumber ) )\r
+    {\r
+        printf("\r\nconfigNETWORK_INTERFACE_TO_USE is not in the valid range.\r\n" );\r
+               \r
+               if( pxAllNetworkInterfaces != NULL )\r
+               {\r
+                       /* Free the device list, as no devices are going to be opened. */\r
+                       pcap_freealldevs( pxAllNetworkInterfaces );\r
+                       pxAllNetworkInterfaces = NULL;\r
+               }\r
+    }\r
+\r
+       return pxAllNetworkInterfaces;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces )\r
+{\r
+pcap_if_t *xInterface;\r
+long x;\r
+\r
+    /* Walk the list of devices until the selected device is located. */\r
+       xInterface = pxAllNetworkInterfaces;\r
+    for( x = 0L; x < ( configNETWORK_INTERFACE_TO_USE - 1L ); x++ )\r
+       {\r
+               xInterface = xInterface->next;\r
+       }\r
+\r
+    /* Open the selected interface. */\r
+       pxOpenedInterfaceHandle = pcap_open(    xInterface->name,               /* The name of the selected interface. */\r
+                                                                                       UIP_CONF_BUFFER_SIZE,           /* The size of the packet to capture. */\r
+                                                                                       PCAP_OPENFLAG_PROMISCUOUS,      /* Open in promiscious mode as the MAC and \r
+                                                                                                                                               IP address is going to be "simulated", and \r
+                                                                                                                                               not be the real MAC and IP address.  This allows\r
+                                                                                                                                               trafic to the simulated IP address to be routed\r
+                                                                                                                                               to uIP, and trafic to the real IP address to be\r
+                                                                                                                                               routed to the Windows TCP/IP stack. */\r
+                                                                                       0xfffffffL,                     /* The read time out.  This is going to block\r
+                                                                                                                                               until data is available. */\r
+                                                                                       NULL,                                   /* No authentication is required as this is\r
+                                                                                                                                               not a remote capture session. */\r
+                                                                                       cErrorBuffer            \r
+                                                                          );\r
+                                                                          \r
+    if ( pxOpenedInterfaceHandle == NULL )\r
+    {\r
+        printf( "\r\n%s is not supported by WinPcap and cannot be opened\r\n", xInterface->name );\r
+    }\r
+       else\r
+       {\r
+               /* Configure the capture filter to allow blocking reads, and to filter \r
+               out packets that are not of interest to this demo. */\r
+               prvConfigureCaptureBehaviour();\r
+       }\r
+\r
+       /* The device list is no longer required. */\r
+       pcap_freealldevs( pxAllNetworkInterfaces );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvConfigureCaptureBehaviour( void )\r
+{\r
+struct bpf_program xFilterCode;\r
+const long lMinBytesToCopy = 10L, lBlocking = 0L;\r
+unsigned long ulNetMask;\r
+\r
+       /* Unblock a read as soon as anything is received. */\r
+       pcap_setmintocopy( pxOpenedInterfaceHandle, lMinBytesToCopy );\r
+\r
+       /* Allow blocking. */\r
+       pcap_setnonblock( pxOpenedInterfaceHandle, lBlocking, cErrorBuffer );\r
+\r
+       /* Set up a filter so only the packets of interest are passed to the uIP\r
+       stack.  cErrorBuffer is used for convenience to create the string.  Don't\r
+       confuse this with an error message. */\r
+       sprintf( cErrorBuffer, "broadcast or multicast or host %d.%d.%d.%d", configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 );\r
+\r
+       ulNetMask = ( configNET_MASK3 << 24UL ) | ( configNET_MASK2 << 16UL ) | ( configNET_MASK1 << 8L ) | configNET_MASK0;\r
+\r
+       if( pcap_compile(pxOpenedInterfaceHandle, &xFilterCode, cErrorBuffer, 1, ulNetMask ) < 0 )\r
+    {\r
+        printf("\r\nThe packet filter string is invalid\r\n" );\r
+    }\r
+       else\r
+       {    \r
+               if( pcap_setfilter( pxOpenedInterfaceHandle, &xFilterCode ) < 0 )\r
+               {\r
+                       printf( "\r\nAn error occurred setting the packet filter.\r\n" );\r
+               }\r
+       }\r
+\r
+       /* Create a task that simulates an interrupt in a real system.  This will\r
+       block waiting for packets, then send a message to the uIP task when data\r
+       is available. */\r
+       xTaskCreate( prvInterruptSimulator, ( signed char * ) "MAC_ISR", configMINIMAL_STACK_SIZE, NULL, ( configuIP_TASK_PRIORITY - 1 ), NULL );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvInterruptSimulator( void *pvParameters )\r
+{\r
+static struct pcap_pkthdr *pxHeader;\r
+const unsigned char *pucPacketData;\r
+extern QueueHandle_t xEMACEventQueue;\r
+const unsigned long ulRxEvent = uipETHERNET_RX_EVENT;\r
+long lResult;\r
+\r
+       /* Just to kill the compiler warning. */\r
+       ( void ) pvParameters;\r
+\r
+       for( ;; )\r
+       {\r
+               /* Get the next packet. */\r
+               lResult = pcap_next_ex( pxOpenedInterfaceHandle, &pxHeader, &pucPacketData );\r
+               if( lResult )\r
+               {\r
+                       /* Is the next buffer into which data should be placed free? */\r
+                       if( lLengthOfDataInBuffer[ ucNextBufferToFill ] == 0L )\r
+                       {\r
+                               /* Copy the data from the captured packet into the buffer. */\r
+                               memcpy( pucEthernetBufferPointers[ ucNextBufferToFill ], pucPacketData, pxHeader->len );\r
+\r
+                               /* Note the amount of data that was copied. */\r
+                               lLengthOfDataInBuffer[ ucNextBufferToFill ] = pxHeader->len;\r
+\r
+                               /* Move onto the next buffer, wrapping around if necessary. */\r
+                               ucNextBufferToFill++;\r
+                               if( ucNextBufferToFill >= archNUM_BUFFER_POINTERS )\r
+                               {\r
+                                       ucNextBufferToFill = 0U;\r
+                               }\r
+\r
+                               /* Data was received and stored.  Send a message to the uIP task\r
+                               to let it know. */\r
+                               xQueueSendToBack( xEMACEventQueue, &ulRxEvent, portMAX_DELAY );\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r