]> git.sur5r.net Git - freertos/blob - Demo/Common/ethernet/lwip-1.4.0/ports/win32/WinPCap/arch.c
Start to re-arrange files to include FreeRTOS+ in main download.
[freertos] / Demo / Common / ethernet / lwip-1.4.0 / ports / win32 / WinPCap / arch.c
1 /*\r
2     FreeRTOS V7.1.1 - Copyright (C) 2012 Real Time Engineers Ltd.\r
3         \r
4 \r
5     ***************************************************************************\r
6      *                                                                       *\r
7      *    FreeRTOS tutorial books are available in pdf and paperback.        *\r
8      *    Complete, revised, and edited pdf reference manuals are also       *\r
9      *    available.                                                         *\r
10      *                                                                       *\r
11      *    Purchasing FreeRTOS documentation will not only help you, by       *\r
12      *    ensuring you get running as quickly as possible and with an        *\r
13      *    in-depth knowledge of how to use FreeRTOS, it will also help       *\r
14      *    the FreeRTOS project to continue with its mission of providing     *\r
15      *    professional grade, cross platform, de facto standard solutions    *\r
16      *    for microcontrollers - completely free of charge!                  *\r
17      *                                                                       *\r
18      *    >>> See http://www.FreeRTOS.org/Documentation for details. <<<     *\r
19      *                                                                       *\r
20      *    Thank you for using FreeRTOS, and thank you for your support!      *\r
21      *                                                                       *\r
22     ***************************************************************************\r
23 \r
24 \r
25     This file is part of the FreeRTOS distribution.\r
26 \r
27     FreeRTOS is free software; you can redistribute it and/or modify it under\r
28     the terms of the GNU General Public License (version 2) as published by the\r
29     Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
30     >>>NOTE<<< The modification to the GPL is included to allow you to\r
31     distribute a combined work that includes FreeRTOS without being obliged to\r
32     provide the source code for proprietary components outside of the FreeRTOS\r
33     kernel.  FreeRTOS is distributed in the hope that it will be useful, but\r
34     WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
35     or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
36     more details. You should have received a copy of the GNU General Public\r
37     License and the FreeRTOS license exception along with FreeRTOS; if not it\r
38     can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
39     by writing to Richard Barry, contact details for whom are available on the\r
40     FreeRTOS WEB site.\r
41 \r
42     1 tab == 4 spaces!\r
43     \r
44     ***************************************************************************\r
45      *                                                                       *\r
46      *    Having a problem?  Start by reading the FAQ "My application does   *\r
47      *    not run, what could be wrong?                                      *\r
48      *                                                                       *\r
49      *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
50      *                                                                       *\r
51     ***************************************************************************\r
52 \r
53     \r
54     http://www.FreeRTOS.org - Documentation, training, latest information, \r
55     license and contact details.\r
56     \r
57     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
58     including FreeRTOS+Trace - an indispensable productivity tool.\r
59 \r
60     Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell \r
61     the code with commercial support, indemnification, and middleware, under \r
62     the OpenRTOS brand: http://www.OpenRTOS.com.  High Integrity Systems also\r
63     provide a safety engineered and independently SIL3 certified version under \r
64     the SafeRTOS brand: http://www.SafeRTOS.com.\r
65 */\r
66 \r
67 /* WinPCap includes. */\r
68 #include "pcap.h"\r
69 #include "remote-ext.h"\r
70 \r
71 /* uIP includes. */\r
72 #include "net/uip.h"\r
73 #include "net/uip_arp.h"\r
74 #include "net/clock-arch.h"\r
75 \r
76 /* FreeRTOS includes. */\r
77 #include "FreeRTOS.h"\r
78 #include "task.h"\r
79 #include "queue.h"\r
80 \r
81 /*\r
82  * Query the computer the simulation is being executed on to find the network\r
83  * interfaces it has installed.\r
84  */\r
85 static pcap_if_t * prvPrintAvailableNetworkInterfaces( void );\r
86 \r
87 /*\r
88  * Open the network interface.  The number of the interface to be opened is set\r
89  * by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.\r
90  */\r
91 static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces );\r
92 \r
93 /*\r
94  * Configure the capture filter to allow blocking reads, and to filter out\r
95  * packets that are not of interest to this demo.\r
96  */\r
97 static void prvConfigureCaptureBehaviour( void );\r
98 \r
99 pcap_t *pxOpenedInterfaceHandle = NULL;\r
100 LARGE_INTEGER freq, sys_start_time;\r
101 \r
102 #define archNUM_BUFFERS 5\r
103 #define archNUM_BUFFER_POINTERS ( archNUM_BUFFERS - 1 )\r
104 \r
105 static void prvInterruptSimulator( void *pvParameters );\r
106 \r
107 static unsigned char ucEthernetBuffer[ archNUM_BUFFERS ][ UIP_CONF_BUFFER_SIZE ];\r
108 static unsigned char *pucEthernetBufferPointers[ archNUM_BUFFER_POINTERS ];\r
109 \r
110 static long lLengthOfDataInBuffer[ archNUM_BUFFER_POINTERS ] = { 0 };\r
111 static unsigned char ucNextBufferToFill = 0U, ucNextBufferToProcess = 0U;\r
112 \r
113 unsigned char *uip_buf = NULL;\r
114 char cErrorBuffer[PCAP_ERRBUF_SIZE];\r
115 \r
116 void vNetifTx( void )\r
117 {\r
118         pcap_sendpacket( pxOpenedInterfaceHandle, uip_buf, uip_len );\r
119         pcap_sendpacket( pxOpenedInterfaceHandle, uip_buf, uip_len );\r
120 }\r
121 /*-----------------------------------------------------------*/\r
122 \r
123 unsigned portBASE_TYPE uxNetifRx( void )\r
124 {\r
125 unsigned portBASE_TYPE xDataLen;\r
126 unsigned char *pucTemp;\r
127 \r
128         /* Check there is really data available. */\r
129         xDataLen = lLengthOfDataInBuffer[ ucNextBufferToProcess ];\r
130         if( xDataLen != 0L )\r
131         {\r
132 \r
133                 /* The buffer pointed to by uip_buf is going to change.  Remember which\r
134                 buffer uip_buf is currently pointing to. */\r
135                 pucTemp = uip_buf;\r
136 \r
137                 /* Point uip_buf at the next buffer that contains data. */\r
138                 uip_buf = pucEthernetBufferPointers[ ucNextBufferToProcess ];\r
139 \r
140                 /* The buffer pointed to by \r
141                 pucEthernetBufferPointeres[ ucNextBufferToProcess ] is now in use by\r
142                 uip_buf, but the buffer uip_buf was pointing to on entry to this\r
143                 function is free.  Set \r
144                 pucEthernetBufferPointeres[ ucNextBufferToProcess ] to the free \r
145                 buffer. */\r
146                 pucEthernetBufferPointers[ ucNextBufferToProcess ] = pucTemp;\r
147                 lLengthOfDataInBuffer[ ucNextBufferToProcess ] = 0L;\r
148 \r
149                 ucNextBufferToProcess++;\r
150                 if( ucNextBufferToProcess >= archNUM_BUFFER_POINTERS )\r
151                 {\r
152                         ucNextBufferToProcess = 0L;\r
153                 }\r
154         }\r
155 \r
156         return xDataLen;\r
157 }\r
158 /*-----------------------------------------------------------*/\r
159 \r
160 portBASE_TYPE xNetifInit( void )\r
161 {\r
162 portBASE_TYPE x;\r
163 pcap_if_t *pxAllNetworkInterfaces;\r
164 \r
165         /* Allocate a free buffer to each buffer pointer. */\r
166         for( x = 0; x < sizeof( pucEthernetBufferPointers ) / sizeof( unsigned char * ); x++ )\r
167         {\r
168                 pucEthernetBufferPointers[ x ] = &( ucEthernetBuffer[ x ][ 0 ] );\r
169         }\r
170 \r
171         /* Start with uip_buf pointing to a buffer that is not referenced from the\r
172         pucEthernetBufferPointers[] array. */\r
173         uip_buf = &( ucEthernetBuffer[ archNUM_BUFFERS - 1 ][ 0 ] );\r
174 \r
175         /* Query the computer the simulation is being executed on to find the \r
176         network interfaces it has installed. */\r
177         pxAllNetworkInterfaces = prvPrintAvailableNetworkInterfaces();\r
178         \r
179         /* Open the network interface.  The number of the interface to be opened is \r
180         set by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.\r
181         Calling this function will set the pxOpenedInterfaceHandle variable.  If,\r
182         after calling this function, pxOpenedInterfaceHandle is equal to NULL, then\r
183         the interface could not be opened. */\r
184         if( pxAllNetworkInterfaces != NULL )\r
185         {\r
186                 prvOpenSelectedNetworkInterface( pxAllNetworkInterfaces );\r
187         }\r
188         \r
189 \r
190         return x;\r
191 }\r
192 /*-----------------------------------------------------------*/\r
193 \r
194 static pcap_if_t * prvPrintAvailableNetworkInterfaces( void )\r
195 {    \r
196 pcap_if_t * pxAllNetworkInterfaces = NULL, *xInterface;\r
197 long lInterfaceNumber = 1;\r
198 \r
199     if( pcap_findalldevs_ex( PCAP_SRC_IF_STRING, NULL, &pxAllNetworkInterfaces, cErrorBuffer ) == -1 )\r
200     {\r
201         printf( "\r\nCould not obtain a list of network interfaces\r\n%s\r\n", cErrorBuffer );\r
202         pxAllNetworkInterfaces = NULL;\r
203     }\r
204 \r
205         if( pxAllNetworkInterfaces != NULL )\r
206         {\r
207                 /* Print out the list of network interfaces.  The first in the list\r
208                 is interface '1', not interface '0'. */\r
209                 for( xInterface = pxAllNetworkInterfaces; xInterface != NULL; xInterface = xInterface->next )\r
210                 {\r
211                         printf( "%d. %s", lInterfaceNumber, xInterface->name );\r
212                         \r
213                         if( xInterface->description != NULL )\r
214                         {\r
215                                 printf( " (%s)\r\n", xInterface->description );\r
216                         }\r
217                         else\r
218                         {\r
219                                 printf( " (No description available)\r\n") ;\r
220                         }\r
221                         \r
222                         lInterfaceNumber++;\r
223                 }\r
224         }\r
225 \r
226     if( lInterfaceNumber == 1 )\r
227     {\r
228                 /* The interface number was never incremented, so the above for() loop\r
229                 did not execute meaning no interfaces were found. */\r
230         printf( " \r\nNo network interfaces were found.\r\n" );\r
231         pxAllNetworkInterfaces = NULL;\r
232     }\r
233 \r
234         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
235         printf( "Attempting to open interface number %d.\r\n", configNETWORK_INTERFACE_TO_USE );\r
236         \r
237     if( ( configNETWORK_INTERFACE_TO_USE < 1L ) || ( configNETWORK_INTERFACE_TO_USE > lInterfaceNumber ) )\r
238     {\r
239         printf("\r\nconfigNETWORK_INTERFACE_TO_USE is not in the valid range.\r\n" );\r
240                 \r
241                 if( pxAllNetworkInterfaces != NULL )\r
242                 {\r
243                         /* Free the device list, as no devices are going to be opened. */\r
244                         pcap_freealldevs( pxAllNetworkInterfaces );\r
245                         pxAllNetworkInterfaces = NULL;\r
246                 }\r
247     }\r
248 \r
249         return pxAllNetworkInterfaces;\r
250 }\r
251 /*-----------------------------------------------------------*/\r
252 \r
253 static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces )\r
254 {\r
255 pcap_if_t *xInterface;\r
256 long x;\r
257 \r
258     /* Walk the list of devices until the selected device is located. */\r
259         xInterface = pxAllNetworkInterfaces;\r
260     for( x = 0L; x < ( configNETWORK_INTERFACE_TO_USE - 1L ); x++ )\r
261         {\r
262                 xInterface = xInterface->next;\r
263         }\r
264 \r
265     /* Open the selected interface. */\r
266         pxOpenedInterfaceHandle = pcap_open(    xInterface->name,               /* The name of the selected interface. */\r
267                                                                                         UIP_CONF_BUFFER_SIZE,           /* The size of the packet to capture. */\r
268                                                                                         PCAP_OPENFLAG_PROMISCUOUS,      /* Open in promiscious mode as the MAC and \r
269                                                                                                                                                 IP address is going to be "simulated", and \r
270                                                                                                                                                 not be the real MAC and IP address.  This allows\r
271                                                                                                                                                 trafic to the simulated IP address to be routed\r
272                                                                                                                                                 to uIP, and trafic to the real IP address to be\r
273                                                                                                                                                 routed to the Windows TCP/IP stack. */\r
274                                                                                         0xfffffffL,                     /* The read time out.  This is going to block\r
275                                                                                                                                                 until data is available. */\r
276                                                                                         NULL,                                   /* No authentication is required as this is\r
277                                                                                                                                                 not a remote capture session. */\r
278                                                                                         cErrorBuffer            \r
279                                                                            );\r
280                                                                            \r
281     if ( pxOpenedInterfaceHandle == NULL )\r
282     {\r
283         printf( "\r\n%s is not supported by WinPcap and cannot be opened\r\n", xInterface->name );\r
284     }\r
285         else\r
286         {\r
287                 /* Configure the capture filter to allow blocking reads, and to filter \r
288                 out packets that are not of interest to this demo. */\r
289                 prvConfigureCaptureBehaviour();\r
290         }\r
291 \r
292         /* The device list is no longer required. */\r
293         pcap_freealldevs( pxAllNetworkInterfaces );\r
294 }\r
295 /*-----------------------------------------------------------*/\r
296 \r
297 static void prvConfigureCaptureBehaviour( void )\r
298 {\r
299 struct bpf_program xFilterCode;\r
300 const long lMinBytesToCopy = 10L, lBlocking = 0L;\r
301 unsigned long ulNetMask;\r
302 \r
303         /* Unblock a read as soon as anything is received. */\r
304         pcap_setmintocopy( pxOpenedInterfaceHandle, lMinBytesToCopy );\r
305 \r
306         /* Allow blocking. */\r
307         pcap_setnonblock( pxOpenedInterfaceHandle, lBlocking, cErrorBuffer );\r
308 \r
309         /* Set up a filter so only the packets of interest are passed to the uIP\r
310         stack.  cErrorBuffer is used for convenience to create the string.  Don't\r
311         confuse this with an error message. */\r
312         sprintf( cErrorBuffer, "broadcast or multicast or host %d.%d.%d.%d", configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 );\r
313 \r
314         ulNetMask = ( configNET_MASK3 << 24UL ) | ( configNET_MASK2 << 16UL ) | ( configNET_MASK1 << 8L ) | configNET_MASK0;\r
315 \r
316         if( pcap_compile(pxOpenedInterfaceHandle, &xFilterCode, cErrorBuffer, 1, ulNetMask ) < 0 )\r
317     {\r
318         printf("\r\nThe packet filter string is invalid\r\n" );\r
319     }\r
320         else\r
321         {    \r
322                 if( pcap_setfilter( pxOpenedInterfaceHandle, &xFilterCode ) < 0 )\r
323                 {\r
324                         printf( "\r\nAn error occurred setting the packet filter.\r\n" );\r
325                 }\r
326         }\r
327 \r
328         /* Create a task that simulates an interrupt in a real system.  This will\r
329         block waiting for packets, then send a message to the uIP task when data\r
330         is available. */\r
331         xTaskCreate( prvInterruptSimulator, ( signed char * ) "MAC_ISR", configMINIMAL_STACK_SIZE, NULL, ( configuIP_TASK_PRIORITY - 1 ), NULL );\r
332 }\r
333 /*-----------------------------------------------------------*/\r
334 \r
335 static void prvInterruptSimulator( void *pvParameters )\r
336 {\r
337 static struct pcap_pkthdr *pxHeader;\r
338 const unsigned char *pucPacketData;\r
339 extern xQueueHandle xEMACEventQueue;\r
340 const unsigned long ulRxEvent = uipETHERNET_RX_EVENT;\r
341 long lResult;\r
342 \r
343         /* Just to kill the compiler warning. */\r
344         ( void ) pvParameters;\r
345 \r
346         for( ;; )\r
347         {\r
348                 /* Get the next packet. */\r
349                 lResult = pcap_next_ex( pxOpenedInterfaceHandle, &pxHeader, &pucPacketData );\r
350                 if( lResult )\r
351                 {\r
352                         /* Is the next buffer into which data should be placed free? */\r
353                         if( lLengthOfDataInBuffer[ ucNextBufferToFill ] == 0L )\r
354                         {\r
355                                 /* Copy the data from the captured packet into the buffer. */\r
356                                 memcpy( pucEthernetBufferPointers[ ucNextBufferToFill ], pucPacketData, pxHeader->len );\r
357 \r
358                                 /* Note the amount of data that was copied. */\r
359                                 lLengthOfDataInBuffer[ ucNextBufferToFill ] = pxHeader->len;\r
360 \r
361                                 /* Move onto the next buffer, wrapping around if necessary. */\r
362                                 ucNextBufferToFill++;\r
363                                 if( ucNextBufferToFill >= archNUM_BUFFER_POINTERS )\r
364                                 {\r
365                                         ucNextBufferToFill = 0U;\r
366                                 }\r
367 \r
368                                 /* Data was received and stored.  Send a message to the uIP task\r
369                                 to let it know. */\r
370                                 xQueueSendToBack( xEMACEventQueue, &ulRxEvent, portMAX_DELAY );\r
371                         }\r
372                 }\r
373         }\r
374 }\r
375 \r